Initial Contribution
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e55f344
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,277 @@
+Eclipse Public License - v 2.0
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+ OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial content
+ Distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+ where such changes and/or additions to the Program originate from
+ and are Distributed by that particular Contributor. A Contribution
+ "originates" from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's behalf.
+ Contributions do not include changes or additions to the Program that
+ are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare Derivative Works of, publicly display,
+ publicly perform, Distribute and sublicense the Contribution of such
+ Contributor, if any, and such Derivative Works.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor,
+ if any, in Source Code or other form. This patent license shall
+ apply to the combination of the Contribution and the Program if, at
+ the time the Contribution is added by the Contributor, such addition
+ of the Contribution causes such combination to be covered by the
+ Licensed Patents. The patent license shall not apply to any other
+ combinations which include the Contribution. No hardware per se is
+ licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity.
+ Each Contributor disclaims any liability to Recipient for claims
+ brought by any other entity based on infringement of intellectual
+ property rights or otherwise. As a condition to exercising the
+ rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to Distribute the
+ Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant
+ the copyright license set forth in this Agreement.
+
+ e) Notwithstanding the terms of any Secondary License, no
+ Contributor makes additional grants to any Recipient (other than
+ those set forth in this Agreement) as a result of such Recipient's
+ receipt of the Program under the terms of a Secondary License
+ (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+ a) the Program must also be made available as Source Code, in
+ accordance with section 3.2, and the Contributor must accompany
+ the Program with a statement that the Source Code for the Program
+ is available under this Agreement, and informs Recipients how to
+ obtain it in a reasonable manner on or through a medium customarily
+ used for software exchange; and
+
+ b) the Contributor may Distribute the Program under a license
+ different than this Agreement, provided that such license:
+ i) effectively disclaims on behalf of all other Contributors all
+ warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and
+ implied warranties or conditions of merchantability and fitness
+ for a particular purpose;
+
+ ii) effectively excludes on behalf of all other Contributors all
+ liability for damages, including direct, indirect, special,
+ incidental and consequential damages, such as lost profits;
+
+ iii) does not attempt to limit or alter the recipients' rights
+ in the Source Code under section 3.2; and
+
+ iv) requires any subsequent distribution of the Program by any
+ party to be under a license that satisfies the requirements
+ of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+ a) it must be made available under this Agreement, or if the
+ Program (i) is combined with other material in a separate file or
+ files made available under a Secondary License, and (ii) the initial
+ Contributor attached to the Source Code the notice described in
+ Exhibit A of this Agreement, then the Program may be made available
+ under the terms of such Secondary Licenses, and
+
+ b) a copy of this Agreement must be included with each copy of
+ the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+Exhibit A - Form of Secondary Licenses Notice
+
+"This Source Code may also be made available under the following
+Secondary Licenses when the conditions for such availability set forth
+in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
+version(s), and exceptions or additional permissions here}."
+
+ Simply including a copy of this Agreement, including this Exhibit A
+ is not sufficient to license the Source Code under Secondary Licenses.
+
+ If it is not possible or desirable to put the notice in a particular
+ file, then You may include the notice in a location (such as a LICENSE
+ file in a relevant directory) where a recipient would be likely to
+ look for such a notice.
+
+ You may add additional accurate notices of copyright ownership.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..bb103bf
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,172 @@
+# Notices for Jifa
+
+This content is produced and maintained by the Eclipse Jifa project.
+
+* Project home: https://projects.eclipse.org/projects/technology.jifa
+
+## Trademarks
+
+Eclipse Jifa, and Jifa are trademarks of the Eclipse Foundation.
+
+## Copyright
+
+All content is the property of the respective authors or their employers. For
+more information regarding authorship of content, please consult the listed
+source code repository logs.
+
+## Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License v. 2.0 which is available at
+http://www.eclipse.org/legal/epl-2.0.
+
+SPDX-License-Identifier: EPL-2.0
+
+## Source Code
+
+The project maintains the following source code repositories:
+
+* https://git.eclipse.org/c/jifa/jifa.git
+
+## Third-party Content
+
+This project leverages the following third party content.
+
+lombok (1.18.6)
+
+* License: MIT
+
+commons-io (2.6)
+
+* License: Apache License 2.0
+
+Google Guava (27.1-jre)
+
+* License: Apache License 2.0
+
+Apache Log4j SLF4J Binding (2.11.2)
+
+* License: Apache License 2.0
+
+Google Gson (2.8.6)
+
+* License: Apache License 2.0
+
+Eclipse Vert.x (3.8.3)
+
+* License: Eclipse Public License 2.0
+
+* License: Apache License 2.0
+
+SSHJ (0.27.0)
+
+* License: Apache License 2.0
+
+Aliyun OSS SDK For Java (2.8.3)
+
+* License: Apache License 2.0
+
+Eclipse MAT
+
+* License: Eclipse Public License 1.0
+
+JUnit (4.12)
+
+* License: Eclipse Public License 1.0
+
+vue (2.6.10)
+
+* License: MIT
+
+axios (0.18.1)
+
+* License: MIT
+
+bootstrap-vue (2.0.0-rc.19)
+
+* License: MIT
+
+chart.js (2.8.0)
+
+* License: MIT
+
+echarts (4.6.0)
+
+* License: Apache License 2.0
+
+element-ui (2.13.1)
+
+* License: MIT
+
+font-awesome (4.7.0)
+
+* License: MIT
+
+jquery (3.4.1)
+
+* License: MIT
+
+node-sass (4.14.0)
+
+* License: MIT
+
+popper.js (1.15.0)
+
+* License: MIT
+
+sass-loader (7.1.0)
+
+* License: MIT
+
+tar (4.4.8)
+
+* License: ISC
+
+v-charts (1.9.0)
+
+* License: MIT
+
+v-contextmenu (2.8.0)
+
+* License: MIT
+
+vue-ads-table-tree (2.4.2)
+
+* License: MIT
+
+vue-chartjs (3.4.2)
+
+* License: MIT
+
+vue-click-outside (1.0.7)
+
+* License: MIT
+
+vue-clipboard2 (0.3.0)
+
+* License: MIT
+
+vue-cookies (1.5.13)
+
+* License: MIT
+
+vue-i18n (8.9.0)
+
+* License: MIT
+
+vue-router (3.0.2)
+
+* License: MIT
+
+## Cryptography
+
+Content may contain encryption software. The country in which you are currently
+may have restrictions on the import, possession, and use, and/or re-export to
+another country, of encryption software. BEFORE using any encryption software,
+please check the country's laws, regulations and policies concerning the import,
+possession, or use, and re-export of encryption software, to see if this is
+permitted.
+
+## Contributors:
+
+Alibaba - Initial implementation
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ed24c6c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+## Introduction
+
+Eclipse Jifa uses Vert.x as the main backend framework, and uses Vue 2.0 as the frontend framework.
+
+Currently, supported features:
+
+Heap dump Analysis:
+- Overview
+- Leak Suspects
+- GC Roots
+- Dominator Tree
+- Thread Overview
+- OQL
+- Some other features
+
+## Quick start
+```
+./gradlew build
+
+cd build/distributions && unzip jifa-0.1.zip && cd jifa-0.1
+
+./bin/worker
+
+Jifa will now be reachable at http://localhost:8102.
+```
+
+## Licenses
+[Eclipse Public License 2.0](https://projects.eclipse.org/license/epl-2.0)
diff --git a/backend/build.gradle b/backend/build.gradle
new file mode 100644
index 0000000..6c5c21b
--- /dev/null
+++ b/backend/build.gradle
@@ -0,0 +1,27 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+subprojects {
+ apply plugin: 'java'
+
+ ext {
+ vertx_version = '3.8.3'
+ }
+
+ dependencies {
+ compile 'org.projectlombok:lombok:1.18.6'
+ annotationProcessor 'org.projectlombok:lombok:1.18.6'
+
+ compile 'commons-io:commons-io:2.6'
+ compile 'com.google.guava:guava:27.1-jre'
+ }
+}
diff --git a/backend/common/build.gradle b/backend/common/build.gradle
new file mode 100644
index 0000000..3f141e0
--- /dev/null
+++ b/backend/common/build.gradle
@@ -0,0 +1,28 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+buildscript {
+ archivesBaseName = 'jifa-common'
+}
+
+dependencies {
+ compile "org.apache.logging.log4j:log4j-slf4j-impl:2.11.2"
+
+ compile 'com.google.code.gson:gson:2.8.6'
+
+ compile group: 'io.vertx', name: 'vertx-web', version: "${vertx_version}"
+}
+
+compileJava {
+ targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_1_8
+}
\ No newline at end of file
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/Constant.java b/backend/common/src/main/java/org/eclipse/jifa/common/Constant.java
new file mode 100644
index 0000000..b285887
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/Constant.java
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common;
+
+public interface Constant {
+ String HEADER_CONTENT_TYPE_KEY = "Content-Type";
+ String CONTENT_TYPE_JSON_FORM = "application/json; charset=UTF-8";
+
+ int HTTP_GET_OK_STATUS_CODE = 200;
+ int HTTP_POST_CREATED_STATUS_CODE = 201;
+
+ int HTTP_BAD_REQUEST_STATUS_CODE = 400;
+ int HTTP_FORBIDDEN_REQUEST_STATUS_CODE = 403;
+ int HTTP_INTERNAL_SERVER_ERROR_STATUS_CODE = 500;
+
+ String LINE_SEPARATOR = System.lineSeparator();
+
+ String EMPTY_STRING = "";
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/aux/ErrorCode.java b/backend/common/src/main/java/org/eclipse/jifa/common/aux/ErrorCode.java
new file mode 100644
index 0000000..7deb698
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/aux/ErrorCode.java
@@ -0,0 +1,39 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.aux;
+
+public enum ErrorCode {
+
+ ILLEGAL_ARGUMENT,
+
+ FILE_DOES_NOT_EXIST,
+
+ TRANSFER_ERROR,
+
+ SANITY_CHECK,
+
+ UNKNOWN_ERROR,
+
+ SHOULD_NOT_REACH_HERE,
+ ;
+
+ public boolean isFatal() {
+ switch (this) {
+ case ILLEGAL_ARGUMENT:
+ case FILE_DOES_NOT_EXIST:
+ return false;
+ default:
+ return true;
+ }
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/aux/JifaException.java b/backend/common/src/main/java/org/eclipse/jifa/common/aux/JifaException.java
new file mode 100644
index 0000000..d233cda
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/aux/JifaException.java
@@ -0,0 +1,48 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.aux;
+
+public class JifaException extends RuntimeException {
+
+ private ErrorCode code = ErrorCode.UNKNOWN_ERROR;
+
+ public JifaException() {
+ this(ErrorCode.UNKNOWN_ERROR);
+ }
+
+ public JifaException(String detail) {
+ this(ErrorCode.UNKNOWN_ERROR, detail);
+ }
+
+ public JifaException(ErrorCode code) {
+ this(code, code.name());
+ }
+
+ public JifaException(ErrorCode code, String detail) {
+ super(detail);
+ this.code = code;
+ }
+
+ public JifaException(Throwable cause) {
+ super(cause);
+ }
+
+ public JifaException(ErrorCode errorCode, Throwable cause) {
+ super(cause);
+ this.code = errorCode;
+ }
+
+ public ErrorCode getCode() {
+ return code;
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/enums/FileType.java b/backend/common/src/main/java/org/eclipse/jifa/common/enums/FileType.java
new file mode 100644
index 0000000..2030d59
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/enums/FileType.java
@@ -0,0 +1,41 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.enums;
+
+import static org.eclipse.jifa.common.util.ErrorUtil.shouldNotReachHere;
+
+public enum FileType {
+ HEAP_DUMP("heap-dump"),
+ ;
+
+ private String tag;
+
+ FileType(String tag) {
+ this.tag = tag;
+ }
+
+ public static FileType getByTag(String tag) {
+ for (FileType type : FileType.values()) {
+ if (type.tag.equals(tag)) {
+ return type;
+ }
+ }
+ return shouldNotReachHere();
+ }
+
+ public String getTag() {
+ return tag;
+ }
+}
+
+
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/enums/ProgressState.java b/backend/common/src/main/java/org/eclipse/jifa/common/enums/ProgressState.java
new file mode 100644
index 0000000..a168d6a
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/enums/ProgressState.java
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.enums;
+
+public enum ProgressState {
+
+ NOT_STARTED,
+
+ IN_PROGRESS,
+
+ SUCCESS,
+
+ ERROR,
+ ;
+
+ public boolean isFinal() {
+ return this == SUCCESS || this == ERROR;
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/request/PagingRequest.java b/backend/common/src/main/java/org/eclipse/jifa/common/request/PagingRequest.java
new file mode 100644
index 0000000..993ccdc
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/request/PagingRequest.java
@@ -0,0 +1,40 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.request;
+
+import lombok.Data;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+@Data
+public class PagingRequest {
+
+ // start with 1
+ private int page;
+
+ private int pageSize;
+
+ public PagingRequest(int page, int pageSize) {
+ ASSERT.isTrue(page >= 1 && pageSize >= 1);
+ this.page = page;
+ this.pageSize = pageSize;
+ }
+
+ public int from() {
+ return (page - 1) * pageSize;
+ }
+
+ public int to(int totalSize) {
+ return Math.min(from() + pageSize, totalSize);
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/Assertion.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/Assertion.java
new file mode 100644
index 0000000..38c5377
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/Assertion.java
@@ -0,0 +1,95 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+
+import java.util.Objects;
+import java.util.function.Supplier;
+
+public abstract class Assertion {
+
+ public static final Assertion ASSERT = new Assertion() {
+ };
+
+ protected Assertion() {
+ }
+
+ public Assertion isTrue(boolean expression, ErrorCode errorCode, Supplier<String> message) {
+ if (!expression) {
+ throwEx(errorCode, message.get());
+ }
+ return self();
+ }
+
+ public Assertion isTrue(boolean expression, ErrorCode errorCode, String message) {
+ return isTrue(expression, errorCode, () -> message);
+ }
+
+ public Assertion isTrue(boolean expression, Supplier<String> message) {
+ return isTrue(expression, ErrorCode.SANITY_CHECK, message);
+ }
+
+ public Assertion isTrue(boolean expression, String message) {
+ return isTrue(expression, ErrorCode.SANITY_CHECK, message);
+ }
+
+ public Assertion isTrue(boolean expression, ErrorCode errorCode) {
+ return isTrue(expression, errorCode, errorCode.name());
+ }
+
+ public Assertion isTrue(boolean expression) {
+ return isTrue(expression, ErrorCode.SANITY_CHECK);
+ }
+
+ public Assertion equals(Object expected, Object actual, ErrorCode errorCode, String message) {
+ return isTrue(Objects.equals(expected, actual), errorCode, message);
+ }
+
+ public Assertion equals(Object expected, Object actual, ErrorCode errorCode) {
+ return equals(expected, actual, errorCode, errorCode.name());
+ }
+
+ public Assertion equals(Object expected, Object actual, String message) {
+ return equals(expected, actual, ErrorCode.SANITY_CHECK, message);
+ }
+
+ public Assertion equals(Object expected, Object actual) {
+ return equals(expected, actual, ErrorCode.SANITY_CHECK);
+ }
+
+ public Assertion notNull(Object object, ErrorCode errorCode, Supplier<String> message) {
+ return isTrue(object != null, errorCode, message);
+ }
+
+ public Assertion notNull(Object object, Supplier<String> message) {
+ return notNull(object, ErrorCode.SANITY_CHECK, message);
+ }
+
+ public Assertion notNull(Object object, String message) {
+ return notNull(object, ErrorCode.SANITY_CHECK, () -> message);
+ }
+
+ public Assertion notNull(Object object) {
+ return notNull(object, ErrorCode.SANITY_CHECK, ErrorCode.SANITY_CHECK::name);
+ }
+
+ private Assertion self() {
+ return this;
+ }
+
+ protected void throwEx(ErrorCode errorCode, String message) {
+ throw new JifaException(errorCode, message);
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/ErrorUtil.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/ErrorUtil.java
new file mode 100644
index 0000000..d3f972a
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/ErrorUtil.java
@@ -0,0 +1,36 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class ErrorUtil {
+
+ public static String toString(Throwable t) {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ return sw.toString();
+ }
+
+ public static void throwEx(Exception e) {
+ throw new JifaException(e);
+ }
+
+ public static <T> T shouldNotReachHere() {
+ throw new JifaException(ErrorCode.SHOULD_NOT_REACH_HERE);
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/FileUtil.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/FileUtil.java
new file mode 100644
index 0000000..05e6cfc
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/FileUtil.java
@@ -0,0 +1,53 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import org.eclipse.jifa.common.Constant;
+
+import java.io.*;
+
+import static org.eclipse.jifa.common.util.ErrorUtil.throwEx;
+
+public class FileUtil {
+
+ public static String content(File f) {
+ String result = null;
+ try {
+ result = content(new FileInputStream(f));
+ } catch (FileNotFoundException e) {
+ throwEx(e);
+ }
+ return result;
+ }
+
+ public static String content(InputStream in) {
+ StringBuilder sb = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ sb.append(line).append(Constant.LINE_SEPARATOR);
+ }
+ } catch (IOException e) {
+ throwEx(e);
+ }
+ return sb.toString();
+ }
+
+ public static void write(File f, String msg, boolean append) {
+ try (FileWriter fw = new FileWriter(f, append)) {
+ fw.write(msg);
+ } catch (IOException e) {
+ throwEx(e);
+ }
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/GsonHolder.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/GsonHolder.java
new file mode 100644
index 0000000..1c1ae8a
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/GsonHolder.java
@@ -0,0 +1,21 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import com.google.gson.Gson;
+
+public class GsonHolder {
+
+ public static final Gson GSON = new Gson();
+
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/HTTPRespGuarder.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/HTTPRespGuarder.java
new file mode 100644
index 0000000..bfd5b45
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/HTTPRespGuarder.java
@@ -0,0 +1,96 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.ext.web.RoutingContext;
+import org.eclipse.jifa.common.Constant;
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.vo.ErrorResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.InvocationTargetException;
+
+import static org.eclipse.jifa.common.util.GsonHolder.GSON;
+
+public class HTTPRespGuarder implements Constant {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HTTPRespGuarder.class);
+
+ public static void ok(RoutingContext context) {
+ ok(context, commonStatusCodeOf(context.request().method()), null);
+ }
+
+ public static void ok(RoutingContext context, Object content) {
+ ok(context, commonStatusCodeOf(context.request().method()), content);
+ }
+
+ private static void ok(RoutingContext context, int statusCode, Object content) {
+ HttpServerResponse response = context.response();
+ response.putHeader(Constant.HEADER_CONTENT_TYPE_KEY, Constant.CONTENT_TYPE_JSON_FORM).setStatusCode(statusCode);
+ if (content != null) {
+ response.end((content instanceof String) ? (String) content : GSON.toJson(content));
+ } else {
+ response.end();
+ }
+ }
+
+ public static void fail(RoutingContext context, Throwable t) {
+ if (t instanceof InvocationTargetException && t.getCause() != null) {
+ t = t.getCause();
+ }
+ log(t);
+ context.response()
+ .putHeader(Constant.HEADER_CONTENT_TYPE_KEY, Constant.CONTENT_TYPE_JSON_FORM)
+ .setStatusCode(statusCodeOf(t))
+ .end(GSON.toJson(new ErrorResult(t)));
+ }
+
+ private static int statusCodeOf(Throwable t) {
+ ErrorCode errorCode = ErrorCode.UNKNOWN_ERROR;
+ if (t instanceof JifaException) {
+ errorCode = ((JifaException) t).getCode();
+ }
+
+ if (t instanceof IllegalArgumentException) {
+ errorCode = ErrorCode.ILLEGAL_ARGUMENT;
+ }
+
+ if (errorCode == ErrorCode.ILLEGAL_ARGUMENT) {
+ return HTTP_BAD_REQUEST_STATUS_CODE;
+ }
+ return HTTP_INTERNAL_SERVER_ERROR_STATUS_CODE;
+ }
+
+ private static void log(Throwable t) {
+ boolean shouldLogError = true;
+
+ if (t instanceof JifaException) {
+ shouldLogError = ((JifaException) t).getCode().isFatal();
+ }
+
+ if (shouldLogError) {
+ LOGGER.error("Handle http request failed", t);
+ }
+ }
+
+ private static int commonStatusCodeOf(HttpMethod method) {
+ if (method == HttpMethod.POST) {
+ return Constant.HTTP_POST_CREATED_STATUS_CODE;
+ }
+ return Constant.HTTP_GET_OK_STATUS_CODE;
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/util/PageViewBuilder.java b/backend/common/src/main/java/org/eclipse/jifa/common/util/PageViewBuilder.java
new file mode 100644
index 0000000..b092347
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/util/PageViewBuilder.java
@@ -0,0 +1,67 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.util;
+
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.vo.PageView;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+public class PageViewBuilder {
+
+ public static <S, R> PageView<R> build(Callback<S> callback, PagingRequest paging, Function<S, R> mapper) {
+ List<R> result = IntStream.range(paging.from(), paging.to(callback.totalSize()))
+ .mapToObj(callback::get)
+ .map(mapper)
+ .collect(Collectors.toList());
+ return new PageView<>(paging, callback.totalSize(), result);
+ }
+
+ public static <R> PageView<R> build(Collection<R> total, PagingRequest paging) {
+ List<R> result = total.stream()
+ .skip(paging.from())
+ .limit(paging.getPageSize())
+ .collect(Collectors.toList());
+ return new PageView<>(paging, total.size(), result);
+ }
+
+ public static <S, R> PageView<R> build(Collection<S> total, PagingRequest paging, Function<S, R> mapper) {
+ List<R> result = total.stream()
+ .skip(paging.from())
+ .limit(paging.getPageSize())
+ .map(mapper)
+ .collect(Collectors.toList());
+ return new PageView<>(paging, total.size(), result);
+ }
+
+ public static <R> PageView<R> build(int[] total, PagingRequest paging, IntFunction<R> mapper) {
+ List<R> result = Arrays.stream(total)
+ .skip(paging.from())
+ .limit(paging.getPageSize())
+ .mapToObj(mapper)
+ .collect(Collectors.toList());
+ return new PageView<>(paging, total.length, result);
+ }
+
+ public interface Callback<O> {
+ int totalSize();
+
+ O get(int index);
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/ErrorResult.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/ErrorResult.java
new file mode 100644
index 0000000..dca44c1
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/ErrorResult.java
@@ -0,0 +1,46 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+
+@Data
+public class ErrorResult {
+
+ private ErrorCode errorCode = ErrorCode.UNKNOWN_ERROR;
+
+ private String message;
+
+ public ErrorResult(Throwable t) {
+ if (t instanceof JifaException) {
+ errorCode = ((JifaException) t).getCode();
+ }
+
+ if (t instanceof IllegalArgumentException) {
+ errorCode = ErrorCode.ILLEGAL_ARGUMENT;
+ }
+
+ Throwable cause = t;
+ while (cause.getCause() != null) {
+ cause = cause.getCause();
+ }
+
+ if (cause instanceof JifaException) {
+ message = cause.getMessage();
+ } else {
+ message = cause.getClass().getSimpleName() + ": " + cause.getMessage();
+ }
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/FileInfo.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/FileInfo.java
new file mode 100644
index 0000000..16f3493
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/FileInfo.java
@@ -0,0 +1,35 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+
+@Data
+public class FileInfo {
+
+ private String originalName;
+
+ private String name;
+
+ private long size;
+
+ private FileType type;
+
+ private ProgressState transferState;
+
+ private boolean downloadable;
+
+ private long creationTime;
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/PageView.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/PageView.java
new file mode 100644
index 0000000..fc60688
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/PageView.java
@@ -0,0 +1,43 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import org.eclipse.jifa.common.request.PagingRequest;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class PageView<T> {
+
+ private List<T> data;
+
+ private int page;
+
+ private int pageSize;
+
+ private int totalSize;
+
+ private int filtered;
+
+ public PageView(PagingRequest request, int totalSize, List<T> data) {
+ this.data = data;
+ this.page = request.getPage();
+ this.pageSize = request.getPageSize();
+ this.totalSize = totalSize;
+ }
+
+ public PageView() {
+
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/Progress.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/Progress.java
new file mode 100644
index 0000000..f9ad8ff
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/Progress.java
@@ -0,0 +1,26 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+import org.eclipse.jifa.common.enums.ProgressState;
+
+@Data
+public class Progress {
+
+ private ProgressState state;
+
+ private double percent = 0;
+
+ private String message;
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/Result.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/Result.java
new file mode 100644
index 0000000..a16470f
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/Result.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+
+@Data
+public class Result<R> {
+
+ private R result;
+
+ public Result(R result) {
+ this.result = result;
+ }
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferProgress.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferProgress.java
new file mode 100644
index 0000000..29326f0
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferProgress.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class TransferProgress extends Progress {
+
+ private long totalSize;
+
+ private long transferredSize;
+}
diff --git a/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferringFile.java b/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferringFile.java
new file mode 100644
index 0000000..335a110
--- /dev/null
+++ b/backend/common/src/main/java/org/eclipse/jifa/common/vo/TransferringFile.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.common.vo;
+
+import lombok.Data;
+
+@Data
+public class TransferringFile {
+
+ private String name;
+
+ public TransferringFile(String fileName) {
+ this.name = fileName;
+ }
+}
diff --git a/backend/worker/build.gradle b/backend/worker/build.gradle
new file mode 100644
index 0000000..2d7626d
--- /dev/null
+++ b/backend/worker/build.gradle
@@ -0,0 +1,61 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+buildscript {
+ archivesBaseName = 'jifa-worker'
+}
+
+plugins {
+ id 'application'
+}
+
+distributions {
+ main {
+ baseName = 'jifa'
+ contents {
+ from("${project.rootDir}/build/static") {
+ into "webroot"
+ }
+ }
+ }
+}
+
+dependencies {
+ compile project(':backend:common')
+
+ compile group: 'io.vertx', name: 'vertx-core', version: "${vertx_version}"
+ compile group: 'io.vertx', name: 'vertx-config', version: "${vertx_version}"
+ compile group: 'io.vertx', name: 'vertx-web-client', version: "${vertx_version}"
+
+ compile 'com.hierynomus:sshj:0.27.0'
+
+ compile 'com.aliyun.oss:aliyun-sdk-oss:2.8.3'
+
+ compile files("${project.rootDir}/mat.jar" as String)
+
+ testCompile 'junit:junit:4.12'
+ testCompile group: 'io.vertx', name: 'vertx-unit', version: "${vertx_version}"
+
+ runtimeOnly project(':frontend')
+}
+
+compileJava {
+ targetCompatibility = JavaVersion.VERSION_1_8
+ sourceCompatibility = JavaVersion.VERSION_1_8
+}
+
+test {
+ useJUnit()
+}
+
+mainClassName = 'org.eclipse.jifa.worker.Starter'
+buildDir = "${project.rootDir}/build"
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/Constant.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/Constant.java
new file mode 100644
index 0000000..483e696
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/Constant.java
@@ -0,0 +1,46 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker;
+
+public interface Constant extends org.eclipse.jifa.common.Constant {
+
+ interface Misc {
+ String VERTX_CONFIG_KEY = "jifa.vertx.config";
+ String WORKER_CONFIG_KEY = "jifa.worker.config";
+ String DEFAULT_VERTX_CONFIG = "vertx-config.json";
+ String DEFAULT_WORKER_CONFIG = "worker-config.json";
+
+ String DEFAULT_WORKSPACE = System.getProperty("user.home") + java.io.File.separator + "jifa_workspace";
+
+ String DEFAULT_HOST = "0.0.0.0";
+
+ String WEB_ROOT_KEY = "jifa.webroot";
+ }
+
+ interface Heap {
+ String TOTAL_SIZE_KEY = "totalSize";
+ String SHALLOW_HEAP_KEY = "shallowHeap";
+ String RETAINED_HEAP_KEY = "retainedHeap";
+ }
+
+ interface File {
+ String INFO_FILE_SUFFIX = "-info.json";
+ }
+
+ interface ConfigKey {
+ String WORKSPACE = "workspace";
+ String API_PREFIX = "api.prefix";
+ String SERVER_HOST_KEY = "server.host";
+ String SERVER_PORT_KEY = "server.port";
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/Global.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/Global.java
new file mode 100644
index 0000000..c7f8756
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/Global.java
@@ -0,0 +1,74 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.json.JsonObject;
+import org.eclipse.jifa.worker.support.FileSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+public class Global {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Starter.class);
+
+ public static Vertx VERTX;
+
+ public static String HOST;
+
+ public static int PORT;
+
+ private static JsonObject CONFIG;
+
+ private static String WORKSPACE;
+
+ private static boolean initialized;
+
+ static synchronized void init(Vertx vertx, String host, int port, JsonObject config) {
+ if (initialized) {
+ return;
+ }
+
+ VERTX = vertx;
+ HOST = host;
+ PORT = port;
+ CONFIG = config;
+
+ WORKSPACE = CONFIG.getString(Constant.ConfigKey.WORKSPACE, Constant.Misc.DEFAULT_WORKSPACE);
+ LOGGER.debug("Workspace: {}", WORKSPACE);
+
+ File workspaceDir = new File(WORKSPACE);
+ if (workspaceDir.exists()) {
+ ASSERT.isTrue(workspaceDir.isDirectory(), "Workspace must be directory");
+ } else {
+ ASSERT.isTrue(workspaceDir.mkdirs(),
+ () -> "Can not create workspace: " + workspaceDir.getAbsolutePath());
+ }
+
+ FileSupport.init();
+
+ initialized = true;
+ }
+
+ public static String stringConfig(String key) {
+ return CONFIG.getString(key);
+ }
+
+ public static String workspace() {
+ return WORKSPACE;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/Starter.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/Starter.java
new file mode 100644
index 0000000..fe07a83
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/Starter.java
@@ -0,0 +1,130 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker;
+
+import com.google.common.base.Strings;
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.DeploymentOptions;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpServer;
+import io.vertx.core.json.JsonObject;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.handler.BodyHandler;
+import io.vertx.ext.web.handler.CorsHandler;
+import io.vertx.ext.web.handler.StaticHandler;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.eclipse.jifa.worker.route.RouteFiller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.charset.Charset;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+
+import static org.eclipse.jifa.worker.Constant.ConfigKey.SERVER_HOST_KEY;
+import static org.eclipse.jifa.worker.Constant.ConfigKey.SERVER_PORT_KEY;
+import static org.eclipse.jifa.worker.Constant.Misc.*;
+
+public class Starter extends AbstractVerticle {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Starter.class);
+
+ private static CountDownLatch count;
+
+ public static void main(String[] args) throws Exception {
+ long start = System.currentTimeMillis();
+
+ JsonObject vc = new JsonObject(readConfig(VERTX_CONFIG_KEY, DEFAULT_VERTX_CONFIG));
+ Vertx vertx = Vertx.vertx(new VertxOptions(vc));
+ JsonObject wc = new JsonObject(readConfig(WORKER_CONFIG_KEY, DEFAULT_WORKER_CONFIG));
+ int processors = Runtime.getRuntime().availableProcessors();
+
+ count = new CountDownLatch(processors);
+ vertx.deployVerticle(Starter.class.getName(), new DeploymentOptions().setConfig(wc).setInstances(processors));
+ count.await();
+
+ LOGGER.info("Jifa-Worker startup successfully in {} ms, verticle count = {}, http server = {}:{}",
+ System.currentTimeMillis() - start, processors, Global.HOST, Global.PORT);
+ }
+
+ private static String readConfig(String key, String def) throws IOException {
+ String v = System.getProperty(key);
+ return Strings.isNullOrEmpty(v)
+ ? IOUtils.toString(Objects.requireNonNull(Starter.class.getClassLoader().getResource(def)),
+ Charset.defaultCharset())
+ : FileUtils.readFileToString(new File(v), Charset.defaultCharset());
+ }
+
+ private static int randomPort() {
+ try {
+ ServerSocket socket = new ServerSocket(0);
+ int port = socket.getLocalPort();
+ socket.close();
+ return port;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void start() {
+ String host = config().containsKey(SERVER_HOST_KEY) ? config().getString(SERVER_HOST_KEY) : DEFAULT_HOST;
+
+ int port = config().containsKey(SERVER_PORT_KEY) ? config().getInteger(SERVER_PORT_KEY) : randomPort();
+
+ String staticRoot = System.getProperty(WEB_ROOT_KEY, "webroot");
+
+ vertx.executeBlocking(event -> {
+ Global.init(vertx, host, port, config());
+
+ HttpServer server = vertx.createHttpServer();
+ Router router = Router.router(vertx);
+
+ File webRoot = new File(staticRoot);
+ if (webRoot.exists() && webRoot.isDirectory()) {
+ String staticPattern = "^(?!" + Global.stringConfig(Constant.ConfigKey.API_PREFIX) + ").*$";
+ StaticHandler staticHandler = StaticHandler.create();
+ staticHandler.setAllowRootFileSystemAccess(true);
+ staticHandler.setWebRoot(staticRoot);
+ router.routeWithRegex(staticPattern).handler(staticHandler);
+ }
+ // cors
+ router.route().handler(CorsHandler.create("*"));
+ router.post().handler(BodyHandler.create());
+
+ new RouteFiller(router).fill();
+ server.requestHandler(router);
+
+ server.listen(port, host, ar -> {
+ if (ar.succeeded()) {
+ event.complete();
+ } else {
+ event.fail(ar.cause());
+ }
+ });
+ }, ar -> {
+ if (ar.succeeded()) {
+ count.countDown();
+ } else {
+ LOGGER.error("Worker-Verticle startup failed", ar.cause());
+ System.exit(-1);
+ }
+ });
+ }
+
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/AnalysisRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/AnalysisRoute.java
new file mode 100644
index 0000000..4fefaf2
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/AnalysisRoute.java
@@ -0,0 +1,78 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import org.eclipse.jifa.worker.Constant;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.vo.Progress;
+import org.eclipse.jifa.common.vo.Result;
+import org.eclipse.jifa.common.util.FileUtil;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.FileSupport;
+import io.vertx.core.Future;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpServerRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Map;
+
+@MappingPrefix(value = {"/heap-dump/:file"})
+class AnalysisRoute extends BaseRoute {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisRoute.class);
+ private Analyzer helper = Analyzer.getInstance();
+
+ // TODO: not good enough
+ private FileType typeOf(HttpServerRequest request) {
+ String uri = request.uri();
+ String apiPrefix = Global.stringConfig(Constant.ConfigKey.API_PREFIX);
+ int end = uri.indexOf("/", apiPrefix.length() + 1);
+ return FileType.getByTag(uri.substring(apiPrefix.length() + 1, end));
+ }
+
+ @RouteMeta(path = "/isFirstAnalysis")
+ void isFirstAnalysis(HttpServerRequest request, Future<Result<Boolean>> future, @ParamKey("file") String file) {
+ future.complete(new Result<>(helper.isFirstAnalysis(typeOf(request), file)));
+ }
+
+ @RouteMeta(path = "/analyze", method = HttpMethod.POST)
+ void analyze(HttpServerRequest request, Future<Void> future, @ParamKey("file") String file,
+ @ParamMap(keys = {"keep_unreachable_objects", "heap_layout"},
+ mandatory = {false, false}) Map<String, String> options) {
+ helper.analyze(future, typeOf(request), file, options);
+ }
+
+ @RouteMeta(path = "/progressOfAnalysis")
+ void poll(HttpServerRequest request, Future<Progress> future, @ParamKey("file") String file) {
+ future.complete(helper.pollProgress(typeOf(request), file));
+ }
+
+ @RouteMeta(path = "/release", method = HttpMethod.POST)
+ void release(HttpServerRequest request, Future<Void> future, @ParamKey("file") String file) {
+ helper.release(file);
+ future.complete();
+ }
+
+ @RouteMeta(path = "/clean", method = HttpMethod.POST)
+ void clean(HttpServerRequest request, Future<Void> future, @ParamKey("file") String file) {
+ helper.clean(typeOf(request), file);
+ future.complete();
+ }
+
+ @RouteMeta(path = "/errorLog")
+ void failedLog(HttpServerRequest request, Future<Result<String>> future, @ParamKey("file") String file) {
+ future.complete(new Result<>(FileUtil.content(new File(FileSupport.errorLogPath(typeOf(request), file)))));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/BaseRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/BaseRoute.java
new file mode 100644
index 0000000..515da46
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/BaseRoute.java
@@ -0,0 +1,16 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+public abstract class BaseRoute {
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/FileRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/FileRoute.java
new file mode 100644
index 0000000..db7a4b0
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/FileRoute.java
@@ -0,0 +1,226 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import io.vertx.core.Future;
+import io.vertx.core.file.FileSystem;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.ext.web.FileUpload;
+import io.vertx.ext.web.RoutingContext;
+import org.apache.logging.log4j.util.Strings;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.HTTPRespGuarder;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.FileInfo;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.vo.TransferProgress;
+import org.eclipse.jifa.common.vo.TransferringFile;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.worker.support.FileSupport;
+import org.eclipse.jifa.worker.support.heapdump.TransferListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import static org.eclipse.jifa.common.Constant.EMPTY_STRING;
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class FileRoute extends BaseRoute {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FileRoute.class);
+
+ @RouteMeta(path = "/files")
+ void list(Future<PageView<FileInfo>> future, @ParamKey("type") FileType type, PagingRequest paging) {
+ List<FileInfo> info = FileSupport.info(type);
+ info.sort((i1, i2) -> Long.compare(i2.getCreationTime(), i1.getCreationTime()));
+ future.complete(PageViewBuilder.build(info, paging));
+ }
+
+ @RouteMeta(path = "/file")
+ void file(Future<FileInfo> future, @ParamKey("type") FileType type, @ParamKey("name") String name) {
+ future.complete(FileSupport.info(type, name));
+ }
+
+ @RouteMeta(path = "/file/delete", method = HttpMethod.POST)
+ void delete(Future<Void> future, @ParamKey("type") FileType type, @ParamKey("name") String name) {
+ FileSupport.delete(type, name);
+ future.complete();
+ }
+
+ @RouteMeta(path = "/publicKey")
+ void publicKeys(Future<String> future) {
+ if (FileSupport.PUB_KEYS.size() > 0) {
+ future.complete(FileSupport.PUB_KEYS.get(0));
+ } else {
+ future.complete(EMPTY_STRING);
+ }
+ }
+
+ private String decorateFileName(String fileName) {
+ return System.currentTimeMillis() + "-" + fileName;
+ }
+
+ private String extractFileName(String path) {
+ return path.substring(path.lastIndexOf(File.separatorChar) + 1);
+ }
+
+ @RouteMeta(path = "/file/transferByURL", method = HttpMethod.POST)
+ void transferByURL(Future<TransferringFile> future, @ParamKey("type") FileType fileType,
+ @ParamKey("url") String url, @ParamKey(value = "fileName", mandatory = false) String fileName) {
+
+ String originalName = extractFileName(url);
+
+ fileName = Strings.isNotBlank(fileName) ? fileName : decorateFileName(originalName);
+
+ TransferListener listener = FileSupport.createTransferListener(fileType, originalName, fileName);
+
+ FileSupport.transferByURL(url, fileType, fileName, listener, future);
+ }
+
+ @RouteMeta(path = "/file/transferByOSS", method = HttpMethod.POST)
+ void transferByOSS(Future<TransferringFile> future, @ParamKey("type") FileType fileType,
+ @ParamKey("endpoint") String endpoint, @ParamKey("accessKeyId") String accessKeyId,
+ @ParamKey("accessKeySecret") String accessKeySecret, @ParamKey("bucketName") String bucketName,
+ @ParamKey("objectName") String objectName,
+ @ParamKey(value = "fileName", mandatory = false) String fileName) {
+
+ String originalName = extractFileName(objectName);
+ fileName = Strings.isNotBlank(fileName) ? fileName : decorateFileName(originalName);
+
+ TransferListener listener = FileSupport.createTransferListener(fileType, originalName, fileName);
+
+ FileSupport.transferByOSS(endpoint, accessKeyId, accessKeySecret, bucketName, objectName,
+ fileType, fileName, listener, future);
+ }
+
+ @RouteMeta(path = "/file/transferBySCP", method = HttpMethod.POST)
+ void transferBySCP(Future<TransferringFile> future, @ParamKey("type") FileType fileType,
+ @ParamKey("hostname") String hostname, @ParamKey("path") String path,
+ @ParamKey("user") String user, @ParamKey("usePublicKey") boolean usePublicKey,
+ @ParamKey(value = "password", mandatory = false) String password,
+ @ParamKey(value = "fileName", mandatory = false) String fileName) {
+
+ if (!usePublicKey) {
+ ASSERT.isTrue(password != null && password.length() > 0,
+ "Must provide password if you don't use public key");
+ }
+
+ String originalName = extractFileName(path);
+ fileName = Strings.isNotBlank(fileName) ? fileName : decorateFileName(extractFileName(path));
+ TransferListener listener = FileSupport.createTransferListener(fileType, originalName, fileName);
+ // do transfer
+ if (usePublicKey) {
+ FileSupport.transferBySCP(user, hostname, path, fileType, fileName, listener, future);
+ } else {
+ FileSupport.transferBySCP(user, password, hostname, path, fileType, fileName, listener, future);
+ }
+ }
+
+ @RouteMeta(path = "/file/transferByFileSystem", method = HttpMethod.POST)
+ void transferByFileSystem(Future<TransferringFile> future, @ParamKey("type") FileType fileType,
+ @ParamKey("path") String path, @ParamKey("move") boolean move) {
+ File src = new File(path);
+ ASSERT.isTrue(src.exists() && !src.isDirectory(), "Illegal path");
+
+ String originalName = extractFileName(path);
+ String fileName = decorateFileName(originalName);
+
+ future.complete(new TransferringFile(fileName));
+ TransferListener listener = FileSupport.createTransferListener(fileType, originalName, fileName);
+
+ listener.setTotalSize(src.length());
+ listener.updateState(ProgressState.IN_PROGRESS);
+ if (move) {
+ Global.VERTX.fileSystem().moveBlocking(path, FileSupport.filePath(fileType, fileName));
+ } else {
+ Global.VERTX.fileSystem().copyBlocking(path, FileSupport.filePath(fileType, fileName));
+ }
+ listener.setTransferredSize(listener.getTotalSize());
+ listener.updateState(ProgressState.SUCCESS);
+ }
+
+ @RouteMeta(path = "/file/transferProgress")
+ void transferProgress(Future<TransferProgress> future, @ParamKey("type") FileType type,
+ @ParamKey("name") String name) {
+ TransferListener listener = FileSupport.getTransferListener(name);
+ if (listener != null) {
+ TransferProgress progress = new TransferProgress();
+ progress.setTotalSize(listener.getTotalSize());
+ progress.setTransferredSize(listener.getTransferredSize());
+ progress.setMessage(listener.getErrorMsg());
+ if (listener.getTotalSize() > 0) {
+ progress.setPercent((double) listener.getTransferredSize() / (double) listener.getTotalSize());
+ }
+ progress.setState(listener.getState());
+
+ if (progress.getState() == ProgressState.SUCCESS || progress.getState() == ProgressState.ERROR) {
+ FileSupport.removeTransferListener(name);
+ }
+ future.complete(progress);
+ } else {
+ FileInfo info = FileSupport.info(type, name);
+ ASSERT.notNull(info);
+ if (info.getTransferState() == ProgressState.IN_PROGRESS
+ || info.getTransferState() == ProgressState.NOT_STARTED) {
+ LOGGER.warn("Illegal file {} state", name);
+ info.setTransferState(ProgressState.ERROR);
+ FileSupport.save(info);
+ }
+ TransferProgress progress = new TransferProgress();
+ progress.setState(info.getTransferState());
+ if (progress.getState() == ProgressState.SUCCESS) {
+ progress.setPercent(1.0);
+ progress.setTotalSize(info.getSize());
+ progress.setTransferredSize(info.getSize());
+ }
+ future.complete(progress);
+ }
+ }
+
+ @RouteMeta(path = "/file/upload", method = HttpMethod.POST)
+ void upload(RoutingContext context, @ParamKey("type") FileType type) {
+ Set<FileUpload> fileUploads = context.fileUploads();
+ for (FileUpload upload : fileUploads) {
+ String fileName = decorateFileName(upload.fileName());
+ FileSupport.initInfoFile(type, upload.fileName(), fileName);
+ FileSystem fileSystem = context.vertx().fileSystem();
+ fileSystem.moveBlocking(upload.uploadedFileName(), FileSupport.filePath(type, fileName));
+ FileSupport.updateTransferState(type, fileName, ProgressState.SUCCESS);
+ }
+ HTTPRespGuarder.ok(context);
+ }
+
+ @RouteMeta(path = "/file/download/:fileType/:filename", contentType = {} /* keep content-type empty */)
+ void download(RoutingContext context, @ParamKey("fileType") FileType fileType, @ParamKey("filename") String name) {
+ File file = new File(FileSupport.filePath(fileType, name));
+ ASSERT.isTrue(file.exists(), "File doesn't exist!");
+ HttpServerResponse response = context.response();
+ response.sendFile(file.getAbsolutePath(), event -> {
+ if (!response.ended()) {
+ response.end();
+ }
+ });
+ }
+
+ @RouteMeta(path = "/file/getOrGenInfo", method = HttpMethod.POST)
+ void getOrGenInfo(Future<FileInfo> future, @ParamKey("fileType") FileType fileType,
+ @ParamKey("filename") String name) {
+ future.complete(FileSupport.getOrGenInfo(fileType, name));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/MappingPrefix.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/MappingPrefix.java
new file mode 100644
index 0000000..882a0fd
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/MappingPrefix.java
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface MappingPrefix {
+ String[] value() default "";
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamKey.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamKey.java
new file mode 100644
index 0000000..2793eb1
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamKey.java
@@ -0,0 +1,27 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface ParamKey {
+
+ String value();
+
+ boolean mandatory() default true;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamMap.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamMap.java
new file mode 100644
index 0000000..ad9601c
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/ParamMap.java
@@ -0,0 +1,28 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.PARAMETER;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(PARAMETER)
+public @interface ParamMap {
+
+ String[] keys();
+
+ boolean[] mandatory();
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteFiller.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteFiller.java
new file mode 100644
index 0000000..afca782
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteFiller.java
@@ -0,0 +1,135 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.Router;
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.util.HTTPRespGuarder;
+import org.eclipse.jifa.worker.Constant;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.worker.route.heapdump.HeapBaseRoute;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class RouteFiller {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(RouteFiller.class);
+
+ private Router router;
+
+ public RouteFiller(Router router) {
+ this.router = router;
+ }
+
+ public void fill() {
+ try {
+ register(FileRoute.class);
+ register(AnalysisRoute.class);
+
+ for (Class<? extends HeapBaseRoute> route : HeapBaseRoute.routes()) {
+ register(route);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String[] buildPrefixes(Class<?> clazz) {
+ ArrayList<String> prefixes = new ArrayList<>();
+ buildPrefix(prefixes, "", clazz);
+ return prefixes.toArray(new String[0]);
+ }
+
+ private void buildPrefix(ArrayList<String> prefixes, String prevPrefix, Class<?> clazz) {
+ if (clazz == null) {
+ String rootPrefix = Global.stringConfig(Constant.ConfigKey.API_PREFIX);
+ prefixes.add(rootPrefix + prevPrefix);
+ return;
+ }
+
+ MappingPrefix anno = clazz.getDeclaredAnnotation(MappingPrefix.class);
+ if (anno == null) {
+ buildPrefix(prefixes, prevPrefix, clazz.getSuperclass());
+ } else {
+ for (int i = 0; i < anno.value().length; i++) {
+ buildPrefix(prefixes, anno.value()[i] + prevPrefix, clazz.getSuperclass());
+ }
+ }
+ }
+
+ private void register(Class<? extends BaseRoute> clazz) throws Exception {
+ Constructor<? extends BaseRoute> constructor = clazz.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ BaseRoute thisObject = constructor.newInstance();
+
+ String[] prefixes = buildPrefixes(clazz);
+ Method[] methods = clazz.getDeclaredMethods();
+ for (String prefix : prefixes) {
+ for (Method method : methods) {
+ registerMethodRoute(thisObject, prefix, method);
+ }
+ }
+ }
+
+ private void registerMethodRoute(BaseRoute thisObject, String prefix, Method method) {
+ RouteMeta meta = method.getAnnotation(RouteMeta.class);
+ if (meta == null) {
+ return;
+ }
+
+ String fullPath = prefix + meta.path();
+ Route route = router.route(meta.method(), fullPath);
+ Arrays.stream(meta.contentType()).forEach(route::produces);
+ method.setAccessible(true);
+
+ LOGGER.debug("Route: path = {}, method = {}", fullPath, method.toGenericString());
+
+ route.blockingHandler(rc -> {
+ try {
+ // pre-process
+ if (meta.contentType().length > 0) {
+ rc.response().putHeader("content-type", String.join(";", meta.contentType()));
+ }
+
+ List<Object> arguments = new ArrayList<>();
+ Parameter[] params = method.getParameters();
+ for (Parameter param : params) {
+ if (!RouterAnnotationProcessor.processParamKey(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processParamMap(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processPagingRequest(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processHttpServletRequest(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processHttpServletResponse(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processFuture(arguments, rc, method, param) &&
+ !RouterAnnotationProcessor.processRoutingContext(arguments, rc, method, param)
+ ) {
+ throw new JifaException(ErrorCode.ILLEGAL_ARGUMENT,
+ "Illegal parameter meta, method = " + method);
+ }
+
+ }
+ method.invoke(thisObject, arguments.toArray());
+ } catch (Throwable t) {
+ HTTPRespGuarder.fail(rc, t);
+ }
+ }, false);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteMeta.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteMeta.java
new file mode 100644
index 0000000..be764c7
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouteMeta.java
@@ -0,0 +1,31 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import io.vertx.core.http.HttpMethod;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface RouteMeta {
+
+ HttpMethod method() default HttpMethod.GET;
+
+ String path();
+
+ String[] contentType() default {"application/json; charset=utf-8"};
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouterAnnotationProcessor.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouterAnnotationProcessor.java
new file mode 100644
index 0000000..2ef1185
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/RouterAnnotationProcessor.java
@@ -0,0 +1,171 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import com.google.gson.Gson;
+import io.vertx.core.Future;
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.ext.web.RoutingContext;
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.HTTPRespGuarder;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class RouterAnnotationProcessor {
+ private static Map<Class<?>, Function<String, ?>> converter = new HashMap<>();
+
+ static {
+ converter.put(String.class, s -> s);
+ converter.put(Integer.class, Integer::parseInt);
+ converter.put(int.class, Integer::parseInt);
+ converter.put(Long.class, Long::parseLong);
+ converter.put(long.class, Long::parseLong);
+ converter.put(Float.class, Float::parseFloat);
+ converter.put(float.class, Float::parseFloat);
+ converter.put(Double.class, Double::parseDouble);
+ converter.put(double.class, Double::parseDouble);
+ converter.put(Boolean.class, Boolean::parseBoolean);
+ converter.put(boolean.class, Boolean::parseBoolean);
+ converter.put(int[].class, s -> new Gson().fromJson(s, int[].class));
+ }
+
+ static boolean processParamKey(List<Object> arguments, RoutingContext context, Method method, Parameter param) {
+ // param key
+ ParamKey paramKey = param.getAnnotation(ParamKey.class);
+ if (paramKey != null) {
+ String value = context.request().getParam(paramKey.value());
+ ASSERT.isTrue(!paramKey.mandatory() || value != null, ErrorCode.ILLEGAL_ARGUMENT,
+ () -> "Miss request parameter, key = " + paramKey.value());
+ arguments.add(value != null ? convert(method, param, context.request().getParam(paramKey.value())) : null);
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processParamMap(List<Object> arguments, RoutingContext context, Method method, Parameter param) {
+ ParamMap paramMap = param.getAnnotation(ParamMap.class);
+ if (paramMap != null) {
+ Map<String, String> map = new HashMap<>();
+ String[] keys = paramMap.keys();
+ boolean[] mandatory = paramMap.mandatory();
+ for (int j = 0; j < keys.length; j++) {
+ String key = keys[j];
+ String value = context.request().getParam(key);
+ ASSERT.isTrue(!mandatory[j] || value != null, ErrorCode.ILLEGAL_ARGUMENT,
+ () -> "Miss request parameter, key = " + key);
+ if (value != null) {
+ map.put(key, value);
+ }
+ }
+ arguments.add(map);
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processPagingRequest(List<Object> arguments, RoutingContext context, Method method,
+ Parameter param) {
+ if (param.getType() == PagingRequest.class) {
+ int page;
+ int pageSize;
+ try {
+ page = Integer.parseInt(context.request().getParam("page"));
+ pageSize = Integer.parseInt(context.request().getParam("pageSize"));
+ ASSERT.isTrue(page >= 1 && pageSize >= 1, ErrorCode.ILLEGAL_ARGUMENT,
+ "must greater than 1");
+ } catch (Exception e) {
+ throw new JifaException(ErrorCode.ILLEGAL_ARGUMENT, "Paging parameter(page or pageSize) is illegal, " +
+ e.getMessage());
+ }
+ arguments.add(new PagingRequest(page, pageSize));
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processHttpServletRequest(List<Object> arguments, RoutingContext context, Method method,
+ Parameter param) {
+ if (param.getType().equals(HttpServerRequest.class)) {
+ arguments.add(context.request());
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processHttpServletResponse(List<Object> arguments, RoutingContext context, Method method,
+ Parameter param) {
+ if (param.getType().equals(HttpServerResponse.class)) {
+ arguments.add(context.response());
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processFuture(List<Object> arguments, RoutingContext context, Method method, Parameter param) {
+ if (param.getType().equals(Future.class)) {
+ arguments.add(newFuture(context));
+ return true;
+ }
+ return false;
+ }
+
+ static boolean processRoutingContext(List<Object> arguments, RoutingContext context, Method method, Parameter param) {
+ if (param.getType().equals(RoutingContext.class)) {
+ arguments.add(context);
+ return true;
+ }
+ return false;
+ }
+
+ private static Object convert(Method m, Parameter p, String value) {
+ Class<?> type = p.getType();
+ Function<String, ?> f;
+ if (type.isEnum()) {
+ f = s -> {
+ for (Object e : type.getEnumConstants()) {
+ if (((Enum) e).name().equalsIgnoreCase(value)) {
+ return e;
+ }
+ }
+ throw new JifaException(ErrorCode.ILLEGAL_ARGUMENT,
+ "Illegal parameter value, parameter = " + p + ", value = " + value);
+ };
+ } else {
+ f = converter.get(type);
+ }
+ ASSERT.notNull(f, () -> "Unsupported parameter type, method = " + m + ", parameter = " + p);
+ return f.apply(value);
+ }
+
+ private static <T> Future<T> newFuture(io.vertx.ext.web.RoutingContext rc) {
+ Future<T> future = Future.future();
+ future.setHandler(event -> {
+ if (event.succeeded()) {
+ HTTPRespGuarder.ok(rc, event.result());
+ } else {
+ HTTPRespGuarder.fail(rc, event.cause());
+ }
+ });
+ return future;
+ }
+}
\ No newline at end of file
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassLoaderRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassLoaderRoute.java
new file mode 100644
index 0000000..9c0dd8f
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassLoaderRoute.java
@@ -0,0 +1,115 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import io.vertx.core.Future;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.SnapshotContext;
+import org.eclipse.jifa.worker.vo.heapdump.classloader.Record;
+import org.eclipse.jifa.worker.vo.heapdump.classloader.Summary;
+import org.eclipse.mat.query.IDecorator;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.query.IStructuredResult;
+import org.eclipse.mat.snapshot.model.IClass;
+
+import java.lang.reflect.Field;
+import java.util.Map;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class ClassLoaderRoute extends HeapBaseRoute {
+
+ private static final Field NODE_PARENT_FIELD;
+ private static final Field PARENT_NODE_FIELD;
+
+ static {
+ try {
+ NODE_PARENT_FIELD =
+ Class.forName("org.eclipse.mat.inspections.ClassLoaderExplorerQuery$Node").getDeclaredField("parent");
+ NODE_PARENT_FIELD.setAccessible(true);
+
+ PARENT_NODE_FIELD =
+ Class.forName("org.eclipse.mat.inspections.ClassLoaderExplorerQuery$Parent").getDeclaredField("node");
+ PARENT_NODE_FIELD.setAccessible(true);
+ } catch (Exception e) {
+ throw new JifaException(e);
+ }
+ }
+
+ @RouteMeta(path = "/classLoaderExplorer/summary")
+ void summary(Future<Summary> future, @ParamKey("file") String file) throws Exception {
+
+ SnapshotContext.ClassLoaderExplorer explorer = Analyzer.getOrOpenSnapshotContext(file).classLoaderExplorer();
+ Summary summary = new Summary();
+ summary.setTotalSize(explorer.getRecords().size());
+ summary.setDefinedClasses(explorer.getDefinedClasses());
+ summary.setNumberOfInstances(explorer.getNumberOfInstances());
+ future.complete(summary);
+ }
+
+ @RouteMeta(path = "/classLoaderExplorer/classLoader")
+ void classLoaders(Future<PageView<Record>> future, @ParamKey("file") String file,
+ PagingRequest pagingRequest) throws Exception {
+ SnapshotContext.ClassLoaderExplorer explorer = Analyzer.getOrOpenSnapshotContext(file).classLoaderExplorer();
+ IStructuredResult resultContext = (IStructuredResult) explorer.getResultContext();
+ future.complete(PageViewBuilder.build(explorer.getRecords(), pagingRequest, e -> {
+ try {
+ Record r = new Record();
+ r.setObjectId(resultContext.getContext(e).getObjectId());
+ r.setPrefix(((IDecorator) resultContext).prefix(e));
+ r.setLabel((String) resultContext.getColumnValue(e, 0));
+ r.setDefinedClasses((Integer) resultContext.getColumnValue(e, 1));
+ r.setNumberOfInstances((Integer) resultContext.getColumnValue(e, 2));
+ r.setClassLoader(true);
+ r.setHasParent(NODE_PARENT_FIELD.get(e) != null);
+ return r;
+ } catch (Exception ex) {
+ throw new JifaException(ex);
+ }
+ }));
+ }
+
+ @RouteMeta(path = "/classLoaderExplorer/children")
+ void children(Future<PageView<Record>> future, @ParamKey("file") String file,
+ @ParamKey("classLoaderId") int classLoaderId, PagingRequest pagingRequest) throws Exception {
+
+ SnapshotContext.ClassLoaderExplorer explorer = Analyzer.getOrOpenSnapshotContext(file).classLoaderExplorer();
+ IResultTree resultContext = (IResultTree) explorer.getResultContext();
+ Map<Integer, Object> classLoaderIdMap = explorer.getClassLoaderIdMap();
+ Object classLoaderNode = classLoaderIdMap.get(classLoaderId);
+ ASSERT.notNull(classLoaderNode, "Illegal classLoaderId");
+ future.complete(PageViewBuilder.build(resultContext.getChildren(classLoaderNode), pagingRequest, e -> {
+ try {
+ Record r = new Record();
+ r.setObjectId(resultContext.getContext(e).getObjectId());
+ r.setPrefix(((IDecorator) resultContext).prefix(e));
+ r.setLabel((String) resultContext.getColumnValue(e, 0));
+ r.setNumberOfInstances((Integer) resultContext.getColumnValue(e, 2));
+ if (!(e instanceof IClass)) {
+ r.setClassLoader(true);
+ r.setDefinedClasses((Integer) resultContext.getColumnValue(e, 1));
+ r.setHasParent(NODE_PARENT_FIELD.get(PARENT_NODE_FIELD.get(e)) != null);
+ }
+ return r;
+ } catch (Exception ex) {
+ throw new JifaException(ex);
+ }
+ }));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassReferenceRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassReferenceRoute.java
new file mode 100644
index 0000000..996f77e
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ClassReferenceRoute.java
@@ -0,0 +1,111 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import io.vertx.core.Future;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.classreference.Record;
+import org.eclipse.mat.inspections.ClassReferrersQuery;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.query.IContextObjectSet;
+import org.eclipse.mat.query.IIconProvider;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.query.Icons;
+
+import java.net.URL;
+
+class ClassReferenceRoute extends HeapBaseRoute {
+
+ private static int getType(URL icon) {
+ if (icon == Icons.CLASS_IN || icon == Icons.CLASS_OUT) {
+ return ClassReferrersQuery.Type.NEW;
+ } else if (icon == Icons.CLASS_IN_MIXED || icon == Icons.CLASS_OUT_MIXED) {
+ return ClassReferrersQuery.Type.MIXED;
+ } else if (icon == Icons.CLASS_IN_OLD || icon == Icons.CLASS_OUT_OLD) {
+ return ClassReferrersQuery.Type.OLD_FAD;
+ }
+ throw new JifaException();
+ }
+
+ private static Record build(IResultTree result, Object row) {
+ Record record = new Record();
+ record.setLabel((String) result.getColumnValue(row, 0));
+ record.setObjects((Integer) result.getColumnValue(row, 1));
+ record.setShallowSize(((Bytes) result.getColumnValue(row, 2)).getValue());
+ IContextObjectSet context = (IContextObjectSet) result.getContext(row);
+ record.setObjectId(context.getObjectId());
+ record.setObjectIds(context.getObjectIds());
+ record.setType(getType(((IIconProvider) result).getIcon(row)));
+ return record;
+
+ }
+
+ private void process(Future<Object> future, String file, int objectId, boolean inbound) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ ClassReferrersQuery query = new ClassReferrersQuery();
+ query.snapshot = snapshot;
+ query.objects = HeapDumpSupport.buildHeapObjectArgument(new int[]{objectId});
+ query.inbound = inbound;
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ Object node = result.getElements().get(0);
+ future.complete(build(result, node));
+ }
+
+ private void process(Future<Object> future, String file, PagingRequest pagingRequest, int[] objectIds,
+ boolean inbound) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ ClassReferrersQuery query = new ClassReferrersQuery();
+ query.snapshot = snapshot;
+ query.objects = HeapDumpSupport.buildHeapObjectArgument(objectIds);
+ query.inbound = inbound;
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ Object node = result.getElements().get(0);
+ future.complete(PageViewBuilder.build(result.getChildren(node), pagingRequest, e -> build(result, e)));
+ }
+
+ @RouteMeta(path = "/classReference/inbounds/class")
+ void inboundsClassInfo(Future<Object> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+ process(future, file, objectId, true);
+ }
+
+ @RouteMeta(path = "/classReference/outbounds/class")
+ void outboundsClassInfo(Future<Object> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+ process(future, file, objectId, false);
+ }
+
+ @RouteMeta(path = "/classReference/inbounds/children")
+ void inboundsChildren(Future<Object> future, @ParamKey("file") String file, PagingRequest pagingRequest,
+ @ParamKey("objectIds") int[] objectIds) throws Exception {
+ process(future, file, pagingRequest, objectIds, true);
+ }
+
+ @RouteMeta(path = "/classReference/outbounds/children")
+ void outboundsChildren(Future<Object> future, @ParamKey("file") String file, PagingRequest pagingRequest,
+ @ParamKey("objectIds") int[] objectIds) throws Exception {
+ process(future, file, pagingRequest, objectIds, false);
+ }
+
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/CompareRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/CompareRoute.java
new file mode 100644
index 0000000..aedd325
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/CompareRoute.java
@@ -0,0 +1,94 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import io.vertx.core.Future;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.FileInfo;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.FileSupport;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.compare.Record;
+import org.eclipse.jifa.worker.vo.heapdump.compare.Summary;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.snapshot.Histogram;
+import org.eclipse.mat.snapshot.ISnapshot;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+class CompareRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/compare/files")
+ void files(Future<PageView<FileInfo>> future, @ParamKey("file") String source,
+ @ParamKey(value = "expected", mandatory = false) String expected, PagingRequest pagingRequest) {
+ future.complete(PageViewBuilder.build(FileSupport.info(FileType.HEAP_DUMP).stream().filter(
+ fileInfo -> !fileInfo.getName().equals(source) && fileInfo.getTransferState() == ProgressState.SUCCESS)
+ .sorted((i1, i2) -> Long
+ .compare(i2.getCreationTime(), i1.getCreationTime()))
+ .collect(Collectors.toList()), pagingRequest));
+ }
+
+ @RouteMeta(path = "/compare/summary")
+ void summary(Future<Summary> future, @ParamKey("file") String target,
+ @ParamKey("baseline") String baseline) throws Exception {
+
+ ISnapshot targetSnapshot = Analyzer.getOrOpenSnapshotContext(target).getSnapshot();
+ ISnapshot baselineSnapshot = Analyzer.getOrOpenSnapshotContext(baseline).getSnapshot();
+ Histogram targetHistogram = targetSnapshot.getHistogram(HeapDumpSupport.VOID_LISTENER);
+ Histogram baselineHistogram = baselineSnapshot.getHistogram(HeapDumpSupport.VOID_LISTENER);
+ final Histogram delta = targetHistogram.diffWithBaseline(baselineHistogram);
+
+ long totalObjects = 0;
+ long totalShallowHeap = 0;
+ for (Object r : delta.getClassHistogramRecords()) {
+ totalObjects += (long) delta.getColumnValue(r, 1);
+ totalShallowHeap += ((Bytes) delta.getColumnValue(r, 2)).getValue();
+ }
+
+ Summary summary = new Summary();
+ summary.setTotalSize(delta.getClassHistogramRecords().size());
+ summary.setObjects(totalObjects);
+ summary.setShallowSize(totalShallowHeap);
+ future.complete(summary);
+ }
+
+ @SuppressWarnings("unchecked")
+ @RouteMeta(path = "/compare/records")
+ void record(Future<PageView<Record>> future, @ParamKey("file") String target, @ParamKey("baseline") String baseline,
+ PagingRequest pagingRequest) throws Exception {
+
+ ISnapshot targetSnapshot = Analyzer.getOrOpenSnapshotContext(target).getSnapshot();
+ ISnapshot baselineSnapshot = Analyzer.getOrOpenSnapshotContext(baseline).getSnapshot();
+ Histogram targetHistogram = targetSnapshot.getHistogram(HeapDumpSupport.VOID_LISTENER);
+ Histogram baselineHistogram = baselineSnapshot.getHistogram(HeapDumpSupport.VOID_LISTENER);
+ final Histogram delta = targetHistogram.diffWithBaseline(baselineHistogram);
+ ((List) delta.getClassHistogramRecords()).sort((o1, o2) -> Long
+ .compare(((Bytes) delta.getColumnValue(o2, 2)).getValue(),
+ ((Bytes) delta.getColumnValue(o1, 2)).getValue()));
+
+ future.complete(PageViewBuilder.build(delta.getClassHistogramRecords(), pagingRequest, r -> {
+ Record record = new Record();
+ record.setClassName((String) delta.getColumnValue(r, 0));
+ record.setObjects((Long) delta.getColumnValue(r, 1));
+ record.setShallowSize(((Bytes) delta.getColumnValue(r, 2)).getValue());
+ return record;
+ }));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DirectByteBufferRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DirectByteBufferRoute.java
new file mode 100644
index 0000000..5e2ae79
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DirectByteBufferRoute.java
@@ -0,0 +1,69 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.SnapshotContext;
+import org.eclipse.jifa.worker.vo.heapdump.directbytebuffer.Record;
+import org.eclipse.jifa.worker.vo.heapdump.directbytebuffer.Summary;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import io.vertx.core.Future;
+import org.eclipse.mat.query.IResultTable;
+
+class DirectByteBufferRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/directByteBuffer/summary")
+ void summary(Future<Summary> future, @ParamKey("file") String file) throws Exception {
+
+ SnapshotContext.DirectByteBuffer data = Analyzer.getOrOpenSnapshotContext(file).directByteBuffer();
+
+ Summary summary = new Summary();
+ summary.setTotalSize(data.getTotalSize());
+ summary.setPosition(data.getPosition());
+ summary.setLimit(data.getLimit());
+ summary.setCapacity(data.getCapacity());
+ future.complete(summary);
+ }
+
+ @RouteMeta(path = "/directByteBuffer/records")
+ void record(Future<PageView<Record>> future, @ParamKey("file") String file,
+ PagingRequest pagingRequest) throws Exception {
+
+ SnapshotContext.DirectByteBuffer data = Analyzer.getOrOpenSnapshotContext(file).directByteBuffer();
+ IResultTable resultContext = data.getResultContext();
+
+ future.complete(PageViewBuilder.build(new PageViewBuilder.Callback<Object>() {
+ @Override
+ public int totalSize() {
+ return data.getTotalSize();
+ }
+
+ @Override
+ public Object get(int index) {
+ return data.getResultContext().getRow(index);
+ }
+ }, pagingRequest, row -> {
+ Record record = new Record();
+ record.setObjectId(resultContext.getContext(row).getObjectId());
+ record.setLabel(data.label(row));
+ record.setPosition(data.position(row));
+ record.setLimit(data.limit(row));
+ record.setCapacity(data.capacity(row));
+ return record;
+ }));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DominatorTreeRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DominatorTreeRoute.java
new file mode 100644
index 0000000..e5e04ef
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DominatorTreeRoute.java
@@ -0,0 +1,147 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.dominatortree.BaseRecord;
+import org.eclipse.jifa.worker.vo.heapdump.dominatortree.ClassRecord;
+import org.eclipse.jifa.worker.vo.heapdump.dominatortree.DefaultRecord;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.internal.snapshot.inspections.DominatorQuery;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class DominatorTreeRoute extends HeapBaseRoute {
+
+ private static Constructor<?> DEFAULT_NODE;
+
+ static {
+ try {
+ Class<?> clazz = Class.forName("org.eclipse.mat.internal.snapshot.inspections.DominatorQuery$Node");
+ DEFAULT_NODE = clazz.getConstructor(int.class);
+ DEFAULT_NODE.setAccessible(true);
+ ASSERT.notNull(DEFAULT_NODE);
+
+ } catch (Exception e) {
+ throw new JifaException(e);
+ }
+ }
+
+ @RouteMeta(path = "/dominatorTree/roots")
+ void roots(Future<PageView<BaseRecord>> future, @ParamKey("file") String file,
+ @ParamKey("grouping") Grouping grouping, PagingRequest pagingRequest) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ DominatorQuery query = new DominatorQuery();
+ query.snapshot = snapshot;
+ query.groupBy = grouping.internalGroping;
+ DominatorQuery.Tree tree = query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ if (grouping == Grouping.NONE) {
+ future.complete(buildDefaultRecord(snapshot, tree, tree.getElements(), pagingRequest));
+ } else if (grouping == Grouping.BY_CLASS) {
+ future.complete(buildClassRecord(tree, tree.getElements(), pagingRequest));
+ }
+ }
+
+ @RouteMeta(path = "/dominatorTree/children")
+ void children(Future<PageView<BaseRecord>> future, @ParamKey("file") String file,
+ @ParamKey("grouping") Grouping grouping, PagingRequest pagingRequest,
+ @ParamKey("parentObjectId") int parentObjectId) throws Exception {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ DominatorQuery query = new DominatorQuery();
+ query.snapshot = snapshot;
+ query.groupBy = grouping.internalGroping;
+ DominatorQuery.Tree tree = query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ if (grouping == Grouping.NONE) {
+ Object parentNode = DEFAULT_NODE.newInstance(parentObjectId);
+ future.complete(buildDefaultRecord(snapshot, tree, tree.getChildren(parentNode), pagingRequest));
+ } else if (grouping == Grouping.BY_CLASS) {
+
+ }
+ }
+
+ private PageView<BaseRecord> buildDefaultRecord(ISnapshot snapshot, DominatorQuery.Tree tree, List<?> elements,
+ PagingRequest pagingRequest) {
+
+ return PageViewBuilder.build(elements, pagingRequest, e -> {
+ try {
+ DefaultRecord record = new DefaultRecord();
+ int objectId = tree.getContext(e).getObjectId();
+ IObject object = snapshot.getObject(objectId);
+ record.setObjectId(objectId);
+ record.setSuffix(HeapDumpSupport.suffix(object.getGCRootInfo()));
+ record.setObjectType(HeapObject.Type.typeOf(object));
+ record.setGCRoot(snapshot.isGCRoot(objectId));
+ record.setLabel((String) tree.getColumnValue(e, 0));
+ record.setShallowSize(((Bytes) tree.getColumnValue(e, 1)).getValue());
+ record.setRetainedSize(((Bytes) tree.getColumnValue(e, 2)).getValue());
+ record.setPercent((Double) tree.getColumnValue(e, 3));
+ return record;
+ } catch (SnapshotException ex) {
+ throw new JifaException(ex);
+ }
+ });
+ }
+
+ private PageView<BaseRecord> buildClassRecord(DominatorQuery.Tree tree, List<?> elements,
+ PagingRequest pagingRequest) {
+
+ elements.sort((e1, e2) -> ((Bytes) tree.getColumnValue(e2, 3)).compareTo(tree.getColumnValue(e1, 3)));
+
+ return PageViewBuilder.build(elements, pagingRequest, e -> {
+ ClassRecord record = new ClassRecord();
+ int objectId = tree.getContext(e).getObjectId();
+ record.setObjectId(objectId);
+ record.setLabel((String) tree.getColumnValue(e, 0));
+ record.setObjects((Integer) tree.getColumnValue(e, 1));
+ record.setShallowSize(((Bytes) tree.getColumnValue(e, 2)).getValue());
+ record.setRetainedSize(((Bytes) tree.getColumnValue(e, 3)).getValue());
+ record.setPercent((Double) tree.getColumnValue(e, 4));
+ return record;
+ });
+ }
+
+ public enum Grouping {
+
+ NONE(DominatorQuery.Grouping.NONE),
+
+ BY_CLASS(DominatorQuery.Grouping.BY_CLASS),
+
+ BY_CLASSLOADER(DominatorQuery.Grouping.BY_CLASSLOADER),
+
+ BY_PACKAGE(DominatorQuery.Grouping.BY_PACKAGE);
+
+ DominatorQuery.Grouping internalGroping;
+
+ Grouping(DominatorQuery.Grouping internalGroping) {
+ this.internalGroping = internalGroping;
+ }
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DuplicatedClassesRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DuplicatedClassesRoute.java
new file mode 100644
index 0000000..587b647
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/DuplicatedClassesRoute.java
@@ -0,0 +1,84 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.vo.heapdump.duplicatedclass.ClassLoaderRecord;
+import org.eclipse.jifa.worker.vo.heapdump.duplicatedclass.ClassRecord;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.inspections.DuplicatedClassesQuery;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.GCRootInfo;
+import org.eclipse.mat.snapshot.model.IClass;
+
+import java.util.List;
+
+class DuplicatedClassesRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/duplicatedClasses/classes")
+ void classRecords(Future<PageView<ClassRecord>> future, @ParamKey("file") String file,
+ PagingRequest pagingRequest) throws Exception {
+
+ DuplicatedClassesQuery query = new DuplicatedClassesQuery();
+ query.snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ List<?> classes = result.getElements();
+ classes.sort((o1, o2) -> ((List) o2).size() - ((List) o1).size());
+ future.complete(PageViewBuilder.build(classes, pagingRequest, r -> {
+ ClassRecord record = new ClassRecord();
+ record.setLabel((String) result.getColumnValue(r, 0));
+ record.setCount((Integer) result.getColumnValue(r, 1));
+ return record;
+ }));
+ }
+
+ @RouteMeta(path = "/duplicatedClasses/classLoaders")
+ void classLoaderRecords(Future<PageView<ClassLoaderRecord>> future, @ParamKey("file") String file,
+ @ParamKey("index") int index, PagingRequest pagingRequest) throws Exception {
+ DuplicatedClassesQuery query = new DuplicatedClassesQuery();
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ query.snapshot = snapshot;
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ List<?> classes = result.getElements();
+ classes.sort((o1, o2) -> ((List) o2).size() - ((List) o1).size());
+ List<?> classLoaders = (List<?>) classes.get(index);
+ future.complete(PageViewBuilder.build(classLoaders, pagingRequest, r -> {
+ ClassLoaderRecord record = new ClassLoaderRecord();
+ record.setLabel((String) result.getColumnValue(r, 0));
+ record.setDefinedClassesCount((Integer) result.getColumnValue(r, 2));
+ record.setInstantiatedObjectsCount((Integer) result.getColumnValue(r, 3));
+ GCRootInfo[] roots;
+ try {
+ roots = ((IClass) r).getGCRootInfo();
+ } catch (SnapshotException e) {
+ throw new JifaException(e);
+ }
+ int id = ((IClass) r).getClassLoaderId();
+ record.setObjectId(id);
+ record.setGCRoot(snapshot.isGCRoot(id));
+ record.setSuffix(roots != null ? GCRootInfo.getTypeSetAsString(roots) : null);
+ return record;
+ }));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/GCRootRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/GCRootRoute.java
new file mode 100644
index 0000000..08e49f8
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/GCRootRoute.java
@@ -0,0 +1,106 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.gcroot.Result;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.inspections.GCRootsQuery;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+class GCRootRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/GCRoots")
+ void roots(Future<List<Result>> future, @ParamKey("file") String file) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ GCRootsQuery query = new GCRootsQuery();
+ query.snapshot = snapshot;
+
+ IResultTree tree = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ future.complete(tree.getElements().stream().map(e -> {
+ Result r = new Result();
+ r.setClassName((String) tree.getColumnValue(e, 0));
+ r.setObjects((Integer) tree.getColumnValue(e, 1));
+ return r;
+ }).collect(Collectors.toList()));
+ }
+
+ @RouteMeta(path = "/GCRoots/classes")
+ void classes(Future<PageView<Result>> future, @ParamKey("file") String file,
+ @ParamKey("rootTypeIndex") int rootTypeIndex, PagingRequest pagingRequest) throws Exception {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ GCRootsQuery query = new GCRootsQuery();
+ query.snapshot = snapshot;
+
+ IResultTree tree = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ Object root = tree.getElements().get(rootTypeIndex);
+ List<?> classes = tree.getChildren(root);
+ future.complete(PageViewBuilder.build(classes, pagingRequest, clazz -> {
+ Result r = new Result();
+ r.setClassName((String) tree.getColumnValue(clazz, 0));
+ r.setObjects((Integer) tree.getColumnValue(clazz, 1));
+ r.setObjectId(tree.getContext(clazz).getObjectId());
+ return r;
+ }));
+ }
+
+ @RouteMeta(path = "/GCRoots/class/objects")
+ void objects(Future<PageView<HeapObject>> future, @ParamKey("file") String file,
+ @ParamKey("rootTypeIndex") int rootTypeIndex, @ParamKey("classIndex") int classIndex,
+ PagingRequest pagingRequest) throws Exception {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ GCRootsQuery query = new GCRootsQuery();
+ query.snapshot = snapshot;
+
+ IResultTree tree = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ Object root = tree.getElements().get(rootTypeIndex);
+ List<?> classes = tree.getChildren(root);
+ Object clazz = classes.get(classIndex);
+ List<?> objects = tree.getChildren(clazz);
+ future.complete(PageViewBuilder.build(objects, pagingRequest, o -> {
+ try {
+ HeapObject ho = new HeapObject();
+ int objectId = tree.getContext(o).getObjectId();
+ IObject object = snapshot.getObject(objectId);
+ ho.setLabel(object.getDisplayName());
+ ho.setObjectId(objectId);
+ ho.setShallowSize(object.getUsedHeapSize());
+ ho.setRetainedSize(object.getRetainedHeapSize());
+ ho.setObjectType(HeapObject.Type.typeOf(object));
+ ho.setGCRoot(snapshot.isGCRoot(objectId));
+ ho.setSuffix(HeapDumpSupport.suffix(object.getGCRootInfo()));
+ ho.setHasOutbound(true);
+ ho.setHasInbound(true);
+ return ho;
+ } catch (SnapshotException e) {
+ throw new JifaException(e);
+ }
+ }));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HeapBaseRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HeapBaseRoute.java
new file mode 100644
index 0000000..d8690c6
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HeapBaseRoute.java
@@ -0,0 +1,50 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.worker.route.BaseRoute;
+import org.eclipse.jifa.worker.route.MappingPrefix;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@MappingPrefix("/heap-dump/:file")
+public class HeapBaseRoute extends BaseRoute {
+
+ private static List<Class<? extends HeapBaseRoute>> ROUTES = new ArrayList<>();
+
+ static {
+ ROUTES.add(OverviewRoute.class);
+ ROUTES.add(ObjectRoute.class);
+ ROUTES.add(InspectorRoute.class);
+ ROUTES.add(DominatorTreeRoute.class);
+ ROUTES.add(HistogramRoute.class);
+ ROUTES.add(UnreachableObjectsRoute.class);
+ ROUTES.add(ClassLoaderRoute.class);
+ ROUTES.add(DuplicatedClassesRoute.class);
+ ROUTES.add(SystemPropertyRoute.class);
+ ROUTES.add(ThreadRoute.class);
+ ROUTES.add(ObjectListRoute.class);
+ ROUTES.add(ClassReferenceRoute.class);
+ ROUTES.add(OQLRoute.class);
+ ROUTES.add(DirectByteBufferRoute.class);
+ ROUTES.add(GCRootRoute.class);
+ ROUTES.add(PathToGCRootsRoute.class);
+ ROUTES.add(CompareRoute.class);
+ ROUTES.add(LeakRoute.class);
+ }
+
+ public static List<Class<? extends HeapBaseRoute>> routes() {
+ return ROUTES;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HistogramRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HistogramRoute.java
new file mode 100644
index 0000000..58e2e50
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/HistogramRoute.java
@@ -0,0 +1,101 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.vo.heapdump.histogram.Record;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.inspections.HistogramQuery;
+import org.eclipse.mat.query.IResult;
+import org.eclipse.mat.snapshot.ClassHistogramRecord;
+import org.eclipse.mat.snapshot.Histogram;
+import org.eclipse.mat.snapshot.ISnapshot;
+
+import java.util.List;
+
+class HistogramRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/histogram")
+ void histogram(Future<PageView<Record>> future, @ParamKey("file") String file,
+ @ParamKey("groupingBy") Grouping groupingBy, @ParamKey(value = "ids", mandatory = false) int[] ids,
+ PagingRequest pagingRequest) throws Exception {
+ try {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ HistogramQuery query = new HistogramQuery();
+ query.snapshot = snapshot;
+ if (ids != null) {
+ query.objects = HeapDumpSupport.buildHeapObjectArgument(ids);
+ }
+
+ query.groupBy = groupingBy.gb;
+
+ IResult result;
+ result = query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ if (groupingBy.gb == HistogramQuery.Grouping.BY_CLASS) {
+
+ Histogram histogram = (Histogram) result;
+ List<ClassHistogramRecord> records = (List) histogram.getClassHistogramRecords();
+ records.forEach(record -> {
+ try {
+ record.calculateRetainedSize(snapshot, true, true, HeapDumpSupport.VOID_LISTENER);
+ } catch (SnapshotException e) {
+ throw new JifaException(e);
+ }
+ });
+ records.sort((o1, o2) -> (int) (o2.getUsedHeapSize() - o1.getUsedHeapSize()));
+ future.complete(PageViewBuilder.build(records, pagingRequest,
+ record -> new Record(record.getClassId(), record.getLabel(),
+ Record.Type.CLASS,
+ record.getNumberOfObjects(),
+ record.getUsedHeapSize(),
+ record.getRetainedHeapSize(),
+ record.getNumberOfYoungObjects(),
+ record.getUsedHeapSizeOfYoung(),
+ record.getNumberOfOldObjects(),
+ record.getUsedHeapSizeOfOld())));
+ } else {
+ // unsupported now.
+ throw new IllegalArgumentException();
+ }
+ } catch (Exception e) {
+ throw new JifaException(e);
+ }
+ }
+
+ public enum Grouping {
+
+ BY_CLASS(HistogramQuery.Grouping.BY_CLASS),
+
+ BY_SUPERCLASS(HistogramQuery.Grouping.BY_SUPERCLASS),
+
+ BY_CLASSLOADER(HistogramQuery.Grouping.BY_CLASSLOADER),
+
+ BY_PACKAGE(HistogramQuery.Grouping.BY_PACKAGE);
+
+ HistogramQuery.Grouping gb;
+
+ Grouping(HistogramQuery.Grouping groupingBy) {
+ this.gb = groupingBy;
+ }
+ }
+
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/InspectorRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/InspectorRoute.java
new file mode 100644
index 0000000..6381d7a
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/InspectorRoute.java
@@ -0,0 +1,206 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.worker.route.MappingPrefix;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.inspector.FieldView;
+import org.eclipse.jifa.worker.vo.heapdump.inspector.ObjectView;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.eclipse.jifa.common.Constant.EMPTY_STRING;
+
+@MappingPrefix("/inspector")
+class InspectorRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/addressToId")
+ void addressToId(Future<Integer> future, @ParamKey("file") String file,
+ @ParamKey("objectAddress") long address) throws SnapshotException {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ future.complete(snapshot.mapAddressToId(address));
+ }
+
+ @RouteMeta(path = "/value")
+ void value(Future<String> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws SnapshotException {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IObject object = snapshot.getObject(objectId);
+
+ String txt = object.getClassSpecificName();
+
+ future.complete(txt != null ? txt : EMPTY_STRING);
+ }
+
+ @RouteMeta(path = "/objectView")
+ void objectView(Future<ObjectView> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws SnapshotException {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IObject object = snapshot.getObject(objectId);
+ ObjectView view = new ObjectView();
+
+ // object address and name
+ // for non-class object, name = the name of object's class
+ // for class object, name = class name
+ view.setObjectAddress(object.getObjectAddress());
+ IClass iClass = object instanceof IClass ? (IClass) object : object.getClazz();
+ view.setName(iClass.getName());
+ view.setObjectType(HeapObject.Type.typeOf(object));
+ view.setGCRoot(snapshot.isGCRoot(objectId));
+
+ // class name and address of the object
+ IClass clazz = object.getClazz();
+ view.setClassLabel(clazz.getTechnicalName());
+ view.setClassGCRoot(clazz.getGCRootInfo() != null);
+
+ // super class name
+ if (iClass.getSuperClass() != null) {
+ view.setSuperClassName(iClass.getSuperClass().getName());
+ }
+
+ // class loader name and address
+ IObject classLoader = snapshot.getObject(iClass.getClassLoaderId());
+ view.setClassLoaderLabel(classLoader.getTechnicalName());
+ view.setClassLoaderGCRoot(classLoader.getGCRootInfo() != null);
+
+ view.setShallowSize(object.getUsedHeapSize());
+ view.setRetainedSize(object.getRetainedHeapSize());
+ // gc root
+ GCRootInfo[] gcRootInfo = object.getGCRootInfo();
+ view.setGcRootInfo(
+ gcRootInfo != null ? "GC root: " + GCRootInfo.getTypeSetAsString(object.getGCRootInfo()) : "no GC root");
+
+ HeapLayout heapLayout = snapshot.getSnapshotInfo().getHeapLayout();
+ view.setLocationType(ObjectView.locationTypeOf(heapLayout.genOf(view.getObjectAddress())));
+ future.complete(view);
+ }
+
+ @RouteMeta(path = "/staticFields")
+ void staticFields(Future<PageView<FieldView>> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId, PagingRequest pagingRequest) throws SnapshotException {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IObject object = snapshot.getObject(objectId);
+ boolean isClass = object instanceof IClass;
+ IClass clazz = isClass ? (IClass) object : object.getClazz();
+
+ List<Field> fields = new ArrayList<>();
+
+ do {
+ List<Field> staticFields = clazz.getStaticFields();
+ for (Field staticField : staticFields) {
+ if (!staticField.getName().startsWith("<")) {
+ fields.add(staticField);
+ }
+ }
+ } while (!isClass && (clazz = clazz.getSuperClass()) != null);
+
+ complete(future, pagingRequest, fields);
+ }
+
+ @RouteMeta(path = "/fields")
+ void fields(Future<PageView<FieldView>> future, @ParamKey("file") String file, @ParamKey("objectId") int objectId,
+ PagingRequest pagingRequest) throws SnapshotException {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IObject object = snapshot.getObject(objectId);
+
+ if (object instanceof IPrimitiveArray) {
+ List<FieldView> fvs = new ArrayList<>();
+ IPrimitiveArray pa = (IPrimitiveArray) object;
+ int firstIndex = (pagingRequest.getPage() - 1) * pagingRequest.getPageSize();
+ int lastIndex = Math.min(firstIndex + pagingRequest.getPageSize(), pa.getLength());
+ for (int i = firstIndex; i < lastIndex; i++) {
+ fvs.add(new FieldView(pa.getType(), "[" + i + "]", pa.getValueAt(i).toString()));
+ }
+ future.complete(new PageView<>(pagingRequest, pa.getLength(), fvs));
+ return;
+ } else if (object instanceof IObjectArray) {
+ List<FieldView> fvs = new ArrayList<>();
+ IObjectArray oa = (IObjectArray) object;
+ int firstIndex = (pagingRequest.getPage() - 1) * pagingRequest.getPageSize();
+ int lastIndex = Math.min(firstIndex + pagingRequest.getPageSize(), oa.getLength());
+ for (int i = firstIndex; i < lastIndex; i++) {
+ long refs[] = oa.getReferenceArray(i, 1);
+ int refObjectId = 0;
+ if (refs[0] != 0) {
+ refObjectId = snapshot.mapAddressToId(refs[0]);
+ }
+ String value = null;
+ if (refObjectId != 0) {
+ value = getObjectValue(snapshot.getObject(refObjectId));
+ }
+ fvs.add(new FieldView(IObject.Type.OBJECT, "[" + i + "]", value, refObjectId));
+ }
+ future.complete(new PageView<>(pagingRequest, oa.getLength(), fvs));
+ return;
+ }
+
+ List<Field> fields = new ArrayList<>();
+ boolean isClass = object instanceof IClass;
+ IClass clazz = isClass ? (IClass) object : object.getClazz();
+
+ if (object instanceof IInstance) {
+ fields.addAll(((IInstance) object).getFields());
+ } else if (object instanceof IClass) {
+ do {
+ List<Field> staticFields = clazz.getStaticFields();
+ for (Field staticField : staticFields) {
+ if (staticField.getName().startsWith("<")) {
+ fields.add(staticField);
+ }
+ }
+ } while ((clazz = clazz.getSuperClass()) != null);
+
+ }
+ complete(future, pagingRequest, fields);
+ }
+
+ private void complete(Future<PageView<FieldView>> future, PagingRequest pagingRequest, List<Field> totalFields) {
+ future.complete(PageViewBuilder.build(totalFields, pagingRequest, field -> {
+ FieldView fv = new FieldView();
+ fv.setFieldType(field.getType());
+ fv.setName(field.getName());
+ Object value = field.getValue();
+ if (value instanceof ObjectReference) {
+ try {
+ fv.setObjectId(((ObjectReference) value).getObjectId());
+ fv.setValue(getObjectValue(((ObjectReference) value).getObject()));
+ } catch (SnapshotException e) {
+ throw new JifaException(e);
+ }
+ } else if (value != null) {
+ fv.setValue(value.toString());
+ }
+ return fv;
+ }));
+ }
+
+ private String getObjectValue(IObject o) {
+ String text = o.getClassSpecificName();
+ return text != null ? text : o.getTechnicalName();
+ }
+
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/LeakRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/LeakRoute.java
new file mode 100644
index 0000000..e922bc2
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/LeakRoute.java
@@ -0,0 +1,145 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import com.google.common.base.Strings;
+import io.vertx.core.Future;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.support.heapdump.SnapshotContext;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.leak.Report;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.internal.Messages;
+import org.eclipse.mat.internal.snapshot.SnapshotQueryContext;
+import org.eclipse.mat.internal.snapshot.inspections.Path2GCRootsQuery;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.query.IResult;
+import org.eclipse.mat.query.IResultPie;
+import org.eclipse.mat.query.refined.RefinedResultBuilder;
+import org.eclipse.mat.query.refined.RefinedTree;
+import org.eclipse.mat.query.results.CompositeResult;
+import org.eclipse.mat.query.results.TextResult;
+import org.eclipse.mat.report.QuerySpec;
+import org.eclipse.mat.report.SectionSpec;
+import org.eclipse.mat.report.Spec;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class LeakRoute extends HeapBaseRoute {
+
+ private static final String OVERVIEW_PATTERN = Messages.LeakHunterQuery_Overview;
+
+ private static final String PROBLEM_SUSPECT_PATTERN =
+ Messages.LeakHunterQuery_ProblemSuspect.substring(0, Messages.LeakHunterQuery_ProblemSuspect.indexOf("{0}"));
+
+ private static final String HIND_PATTERN =
+ Messages.LeakHunterQuery_Hint.substring(0, Messages.LeakHunterQuery_Hint.indexOf("{0}"));
+
+ private static final String DESC_PATTERN = Messages.LeakHunterQuery_Description;
+
+ private static final String SHORTEST_PATHS_PATTERN = Messages.LeakHunterQuery_ShortestPaths;
+
+ @RouteMeta(path = "/leak/report")
+ void report(Future<Report> future, @ParamKey("file") String file) throws Exception {
+ SnapshotContext context = Analyzer.getOrOpenSnapshotContext(file);
+ IResult result = context.leakReport().getResult();
+ Report report = new Report();
+ if (result instanceof TextResult) {
+ report.setInfo(((TextResult) result).getText());
+ } else if (result instanceof SectionSpec) {
+ report.setUseful(true);
+ SectionSpec sectionSpec = (SectionSpec) result;
+ report.setName(sectionSpec.getName());
+ List<Spec> specs = sectionSpec.getChildren();
+ for (int i = 0; i < specs.size(); i++) {
+ QuerySpec spec = (QuerySpec) specs.get(i);
+ String name = spec.getName();
+ if (Strings.isNullOrEmpty(name)) {
+ continue;
+ }
+ if (name.startsWith(OVERVIEW_PATTERN)) {
+ IResultPie irtPie = (IResultPie) spec.getResult();
+ List<? extends IResultPie.Slice> pieSlices = irtPie.getSlices();
+
+ List<Report.Slice> slices = new ArrayList<>();
+ for (IResultPie.Slice slice : pieSlices) {
+ slices.add(new Report.Slice(slice.getLabel(), HeapDumpSupport.fetchObjectId(slice.getContext()),
+ slice.getValue(), slice.getDescription()));
+ }
+ report.setSlices(slices);
+
+ } else if (name.startsWith(PROBLEM_SUSPECT_PATTERN) || name.startsWith(HIND_PATTERN)) {
+ Report.Record suspect = new Report.Record();
+ suspect.setIndex(i);
+ suspect.setName(name);
+ CompositeResult cr = (CompositeResult) spec.getResult();
+ List<CompositeResult.Entry> entries = cr.getResultEntries();
+ for (CompositeResult.Entry entry : entries) {
+ String entryName = entry.getName();
+ if (Strings.isNullOrEmpty(entryName)) {
+ IResult r = entry.getResult();
+ if (r instanceof QuerySpec && ((QuerySpec) r).getName().equals(SHORTEST_PATHS_PATTERN)) {
+ Path2GCRootsQuery.Tree tree = (Path2GCRootsQuery.Tree) ((QuerySpec) r).getResult();
+ RefinedResultBuilder builder = new RefinedResultBuilder(
+ new SnapshotQueryContext(context.getSnapshot()), tree);
+ RefinedTree rst = (RefinedTree) builder.build();
+ List<?> elements = rst.getElements();
+ List<Report.ShortestPath> paths = new ArrayList<>();
+ suspect.setPaths(paths);
+ for (Object row : elements) {
+ paths.add(buildPath(context.getSnapshot(), rst, row));
+ }
+ }
+ } else if ((entryName.startsWith(DESC_PATTERN) || entryName.startsWith(OVERVIEW_PATTERN))) {
+ TextResult desText = (TextResult) entry.getResult();
+ suspect.setDesc(desText.getText());
+ }
+ }
+ List<Report.Record> records = report.getRecords();
+ if (records == null) {
+ report.setRecords(records = new ArrayList<>());
+ }
+ records.add(suspect);
+ }
+ }
+ }
+ future.complete(report);
+ }
+
+ private Report.ShortestPath buildPath(ISnapshot snapshot, RefinedTree rst, Object row) throws SnapshotException {
+ Report.ShortestPath shortestPath = new Report.ShortestPath();
+ shortestPath.setLabel((String) rst.getColumnValue(row, 0));
+ shortestPath.setShallowSize(((Bytes) rst.getColumnValue(row, 1)).getValue());
+ shortestPath.setRetainedSize(((Bytes) rst.getColumnValue(row, 2)).getValue());
+ int objectId = rst.getContext(row).getObjectId();
+ shortestPath.setObjectId(objectId);
+ IObject object = snapshot.getObject(objectId);
+ shortestPath.setGCRoot(snapshot.isGCRoot(objectId));
+ shortestPath.setObjectType(HeapObject.Type.typeOf(object));
+
+ if (rst.hasChildren(row)) {
+ List<Report.ShortestPath> children = new ArrayList<>();
+ shortestPath.setChildren(children);
+ for (Object c : rst.getChildren(row)) {
+ children.add(buildPath(snapshot, rst, c));
+ }
+ }
+ return shortestPath;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OQLRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OQLRoute.java
new file mode 100644
index 0000000..35f6ef3
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OQLRoute.java
@@ -0,0 +1,104 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import io.vertx.core.Future;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.oql.TableResult;
+import org.eclipse.jifa.worker.vo.heapdump.oql.TextResult;
+import org.eclipse.jifa.worker.vo.heapdump.oql.TreeResult;
+import org.eclipse.mat.inspections.OQLQuery;
+import org.eclipse.mat.query.Column;
+import org.eclipse.mat.query.IContextObject;
+import org.eclipse.mat.query.IResultTable;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.snapshot.IOQLQuery;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+class OQLRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/oql")
+ void oql(Future<Object> future, @ParamKey("file") String file, @ParamKey("oql") String oql,
+ PagingRequest pagingRequest) throws Exception {
+ OQLQuery query = new OQLQuery();
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ query.snapshot = snapshot;
+ query.queryString = oql;
+ IOQLQuery.Result qr = query.execute(HeapDumpSupport.VOID_LISTENER);
+
+ if (qr instanceof IResultTree) {
+ future.complete(new TreeResult(PageViewBuilder.build(((IResultTree) qr).getElements(), pagingRequest, e -> {
+ try {
+ int objectId = ((IResultTree) qr).getContext(e).getObjectId();
+ IObject o = snapshot.getObject(objectId);
+ HeapObject ho = new HeapObject();
+ ho.setObjectId(objectId);
+ ho.setLabel(o.getDisplayName());
+ ho.setSuffix(HeapDumpSupport.suffix(o.getGCRootInfo()));
+ ho.setShallowSize(o.getUsedHeapSize());
+ ho.setRetainedSize(o.getRetainedHeapSize());
+ ho.setGCRoot(snapshot.isGCRoot(objectId));
+ ho.setObjectType(HeapObject.Type.typeOf(o));
+ ho.setHasOutbound(true);
+ return ho;
+ } catch (Exception ex) {
+ throw new JifaException(ex);
+ }
+ })));
+ } else if (qr instanceof IResultTable) {
+ IResultTable table = (IResultTable) qr;
+ Column[] columns = table.getColumns();
+ List<String> cs = Arrays.stream(columns).map(Column::getLabel).collect(Collectors.toList());
+ PageView<TableResult.Entry> pv = PageViewBuilder.build(new PageViewBuilder.Callback<Object>() {
+ @Override
+ public int totalSize() {
+ return table.getRowCount();
+ }
+
+ @Override
+ public Object get(int index) {
+ return table.getRow(index);
+ }
+ }, pagingRequest, o -> {
+ List<Object> l = new ArrayList<>();
+ for (int i = 0; i < columns.length; i++) {
+ Object columnValue = table.getColumnValue(o, i);
+
+ l.add(columnValue != null ? columnValue.toString() : null);
+ }
+ IContextObject context = table.getContext(o);
+ return new TableResult.Entry(
+ context != null ? context.getObjectId() : HeapDumpSupport.ILLEGAL_OBJECT_ID, l);
+ });
+ future.complete(new TableResult(cs, pv));
+ } else if (qr instanceof org.eclipse.mat.query.results.TextResult) {
+ future.complete(new TextResult(((org.eclipse.mat.query.results.TextResult) qr).getText()));
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectListRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectListRoute.java
new file mode 100644
index 0000000..62c24d1
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectListRoute.java
@@ -0,0 +1,75 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import io.vertx.core.Future;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class ObjectListRoute extends HeapBaseRoute {
+
+ private static void fill(Future<PageView<HeapObject>> future, ISnapshot snapshot, int src, int[] objId,
+ PagingRequest pagingRequest, boolean outbound) {
+ future.complete(PageViewBuilder.build(objId, pagingRequest, id -> {
+ try {
+ HeapObject o = new HeapObject();
+ IObject object = snapshot.getObject(id);
+ o.setObjectId(id);
+ o.setLabel(object.getDisplayName());
+ o.setShallowSize(object.getUsedHeapSize());
+ o.setRetainedSize(object.getRetainedHeapSize());
+ o.setObjectType(HeapObject.Type.typeOf(object));
+ o.setGCRoot(snapshot.isGCRoot(id));
+ o.setHasOutbound(true);
+ o.setHasInbound(true);
+ o.setPrefix(HeapDumpSupport.prefix(snapshot, outbound ? src : id, outbound ? id : src));
+ o.setSuffix(HeapDumpSupport.suffix(snapshot, id));
+ return o;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }));
+ }
+
+ @RouteMeta(path = "/outbounds")
+ void outbounds(Future<PageView<HeapObject>> future, @ParamKey("file") String file, PagingRequest pagingRequest,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+ ASSERT.isTrue(objectId >= 0, "Object id must be greater than or equal to 0");
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ int[] objId = snapshot.getOutboundReferentIds(objectId);
+ fill(future, snapshot, objectId, objId, pagingRequest, true);
+ }
+
+ @RouteMeta(path = "/inbounds")
+ void inbounds(Future<PageView<HeapObject>> future, @ParamKey("file") String file, PagingRequest pagingRequest,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+ ASSERT.isTrue(objectId >= 0, "Object id must be greater than or equal to 0");
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ int[] objId = snapshot.getInboundRefererIds(objectId);
+ fill(future, snapshot, objectId, objId, pagingRequest, false);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectRoute.java
new file mode 100644
index 0000000..321d54d
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ObjectRoute.java
@@ -0,0 +1,47 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import io.vertx.core.Future;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class ObjectRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/object")
+ void info(Future<HeapObject> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+ ASSERT.isTrue(objectId >= 0, "Object id must be greater than or equal to 0");
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+
+ HeapObject o = new HeapObject();
+ IObject object = snapshot.getObject(objectId);
+ o.setObjectId(objectId);
+ o.setLabel(object.getDisplayName());
+ o.setShallowSize(object.getUsedHeapSize());
+ o.setRetainedSize(object.getRetainedHeapSize());
+ o.setObjectType(HeapObject.Type.typeOf(object));
+ o.setGCRoot(snapshot.isGCRoot(objectId));
+ o.setHasOutbound(true);
+ o.setSuffix(HeapDumpSupport.suffix(snapshot, objectId));
+ future.complete(o);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OverviewRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OverviewRoute.java
new file mode 100644
index 0000000..11a9455
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/OverviewRoute.java
@@ -0,0 +1,56 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import io.vertx.core.Future;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.overview.BigObject;
+import org.eclipse.jifa.worker.vo.heapdump.overview.Details;
+import org.eclipse.mat.inspections.BiggestObjectsPieQuery;
+import org.eclipse.mat.query.IResultPie;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.SnapshotInfo;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+class OverviewRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/details")
+ void details(Future<Details> future, @ParamKey("file") String file) {
+ SnapshotInfo snapshotInfo = Analyzer.getOrOpenSnapshotContext(file).getSnapshot().getSnapshotInfo();
+ Details details = new Details(snapshotInfo.getJvmInfo(), snapshotInfo.getIdentifierSize(),
+ snapshotInfo.getCreationDate().getTime(), snapshotInfo.getNumberOfObjects(),
+ snapshotInfo.getNumberOfGCRoots(), snapshotInfo.getNumberOfClasses(),
+ snapshotInfo.getNumberOfClassLoaders(), snapshotInfo.getUsedHeapSize(),
+ snapshotInfo.layoutAvailable());
+ future.complete(details);
+ }
+
+ @RouteMeta(path = "/biggestObjects")
+ void biggestObjects(Future<List<BigObject>> future, @ParamKey("file") String file) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ BiggestObjectsPieQuery query = new BiggestObjectsPieQuery();
+ query.snapshot = snapshot;
+ List<? extends IResultPie.Slice> slices = query.execute(HeapDumpSupport.VOID_LISTENER).getSlices();
+ future.complete(slices.stream()
+ .map(slice -> new BigObject(slice.getLabel(),
+ slice.getContext() != null ? slice.getContext().getObjectId()
+ : HeapDumpSupport.ILLEGAL_OBJECT_ID,
+ slice.getValue(), slice.getDescription()))
+ .collect(Collectors.toList()));
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/PathToGCRootsRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/PathToGCRootsRoute.java
new file mode 100644
index 0000000..0ff35ea
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/PathToGCRootsRoute.java
@@ -0,0 +1,136 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.gcrootpath.Result;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.snapshot.IPathsFromGCRootsComputer;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.IClass;
+import org.eclipse.mat.snapshot.model.IObject;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class PathToGCRootsRoute extends HeapBaseRoute {
+ private List<String> excludes =
+ Arrays.asList("java.lang.ref.WeakReference:referent", "java.lang.ref.SoftReference:referent");
+
+ private static Map<IClass, Set<String>> convert(ISnapshot snapshot,
+ List<String> excludes) throws SnapshotException {
+ Map<IClass, Set<String>> excludeMap = null;
+
+ if (excludes != null && !excludes.isEmpty()) {
+ excludeMap = new HashMap<IClass, Set<String>>();
+
+ for (String entry : excludes) {
+ String pattern = entry;
+ Set<String> fields = null;
+ int colon = entry.indexOf(':');
+
+ if (colon >= 0) {
+ fields = new HashSet<String>();
+
+ StringTokenizer tokens = new StringTokenizer(entry.substring(colon + 1), ","); //$NON-NLS-1$
+ while (tokens.hasMoreTokens())
+ fields.add(tokens.nextToken());
+
+ pattern = pattern.substring(0, colon);
+ }
+
+ for (IClass clazz : snapshot.getClassesByName(Pattern.compile(pattern), true))
+ excludeMap.put(clazz, fields);
+ }
+ }
+
+ return excludeMap;
+ }
+
+ @RouteMeta(path = "/pathToGCRoots")
+ void path(Future<Result> future, @ParamKey("file") String file, @ParamKey("origin") int origin,
+ @ParamKey("skip") int skip, @ParamKey("count") int count) throws Exception {
+
+ ASSERT.isTrue(origin >= 0).isTrue(skip >= 0).isTrue(count > 0);
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ Map<IClass, Set<String>> excludeMap = convert(snapshot, excludes);
+
+ IPathsFromGCRootsComputer computer = snapshot.getPathsFromGCRoots(origin, excludeMap);
+
+ List<int[]> paths = new ArrayList<>();
+ int index = 0;
+ int[] current;
+ int get = 0;
+ while (get < count && (current = computer.getNextShortestPath()) != null) {
+ if (index < skip) {
+ index++;
+ continue;
+ }
+ paths.add(current);
+ get++;
+ }
+ future.complete(build(snapshot, origin, paths, computer.getNextShortestPath() != null));
+ }
+
+ private Result build(ISnapshot snapshot, int originId, List<int[]> paths, boolean hasMore) throws Exception {
+
+ Result result = new Result();
+ result.setCount(paths.size());
+ result.setHasMore(hasMore);
+ Result.Node origin = new Result.Node();
+ IObject object = snapshot.getObject(originId);
+ origin.setOrigin(true);
+ origin.setObjectId(originId);
+ origin.setLabel(object.getDisplayName());
+ origin.setSuffix(HeapDumpSupport.suffix(snapshot, originId));
+ origin.setGCRoot(snapshot.isGCRoot(originId));
+ origin.setObjectType(HeapObject.Type.typeOf(object));
+ origin.setShallowSize(object.getUsedHeapSize());
+ origin.setRetainedSize(object.getRetainedHeapSize());
+ result.setTree(origin);
+
+ if (paths.size() == 0) {
+ return result;
+ }
+
+ for (int[] path : paths) {
+ Result.Node parentNode = origin;
+ for (int index = 1; index < path.length; index++) {
+ int childId = path[index];
+ Result.Node childNode = parentNode.getChild(childId);
+ if (childNode == null) {
+ IObject childObj = snapshot.getObject(childId);
+ childNode = new Result.Node();
+ childNode.setObjectId(childId);
+ childNode.setPrefix(HeapDumpSupport.prefix(snapshot, childId, parentNode.getObjectId()));
+ childNode.setLabel(childObj.getDisplayName());
+ childNode.setSuffix(HeapDumpSupport.suffix(snapshot, childId));
+ childNode.setGCRoot(snapshot.isGCRoot(childId));
+ childNode.setObjectType(HeapObject.Type.typeOf(childObj));
+ childNode.setShallowSize(childObj.getUsedHeapSize());
+ childNode.setRetainedSize(childObj.getRetainedHeapSize());
+ parentNode.addChild(childNode);
+ }
+ parentNode = childNode;
+ }
+ }
+ return result;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/SystemPropertyRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/SystemPropertyRoute.java
new file mode 100644
index 0000000..2be3a2f
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/SystemPropertyRoute.java
@@ -0,0 +1,41 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import io.vertx.core.Future;
+import org.eclipse.mat.inspections.SystemPropertiesQuery;
+import org.eclipse.mat.query.IResultTable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class SystemPropertyRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/systemProperties")
+ void systemProperty(Future<Map<String, String>> future, @ParamKey("file") String file) throws Exception {
+ SystemPropertiesQuery query = new SystemPropertiesQuery();
+ query.snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IResultTable result = query.execute(HeapDumpSupport.VOID_LISTENER);
+ Map<String, String> sp = new HashMap<>();
+ int count = result.getRowCount();
+ for (int i = 0; i < count; i++) {
+ Object row = result.getRow(i);
+ sp.put((String) result.getColumnValue(row, 1), (String) result.getColumnValue(row, 2));
+ }
+ future.complete(sp);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ThreadRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ThreadRoute.java
new file mode 100644
index 0000000..65b582e
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/ThreadRoute.java
@@ -0,0 +1,198 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.worker.Constant;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import org.eclipse.jifa.worker.vo.heapdump.thread.Info;
+import org.eclipse.jifa.worker.vo.heapdump.thread.LocalVariable;
+import org.eclipse.jifa.worker.vo.heapdump.thread.StackFrame;
+import io.vertx.core.Future;
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.inspections.threads.ThreadOverviewQuery;
+import org.eclipse.mat.internal.Messages;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.GCRootInfo;
+import org.eclipse.mat.snapshot.model.IObject;
+import org.eclipse.mat.snapshot.query.IHeapObjectArgument;
+import org.eclipse.mat.util.IProgressListener;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+
+class ThreadRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/threadsSummary")
+ void threadsSummary(Future<Map<String, Long>> future, @ParamKey("file") String file) throws Exception {
+
+ ThreadOverviewQuery query = new ThreadOverviewQuery();
+ query.snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ List<?> elements = result.getElements();
+ long totalShallowSize = 0;
+ long totalRetainedSize = 0;
+ for (Object t : elements) {
+ totalShallowSize += ((Bytes) result.getColumnValue(t, 2)).getValue();
+ totalRetainedSize += ((Bytes) result.getColumnValue(t, 3)).getValue();
+ }
+ Map<String, Long> info = new HashMap<>();
+ info.put(Constant.Heap.TOTAL_SIZE_KEY, (long) elements.size());
+ info.put(Constant.Heap.SHALLOW_HEAP_KEY, totalShallowSize);
+ info.put(Constant.Heap.RETAINED_HEAP_KEY, totalRetainedSize);
+ future.complete(info);
+ }
+
+ @RouteMeta(path = "/threads")
+ void threads(Future<PageView<Info>> future, @ParamKey("file") String file, PagingRequest paging) throws Exception {
+
+ ThreadOverviewQuery query = new ThreadOverviewQuery();
+ query.snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ List<?> elements = result.getElements();
+
+
+ future.complete(PageViewBuilder.build(elements, paging, e -> new Info(result.getContext(e).getObjectId(),
+ (String) result.getColumnValue(e, 0),
+ (String) result.getColumnValue(e, 1),
+ ((Bytes) result.getColumnValue(e, 2))
+ .getValue(),
+ ((Bytes) result.getColumnValue(e, 3))
+ .getValue(),
+ (String) result.getColumnValue(e, 4),
+ result.hasChildren(e),
+ (Boolean) result.getColumnValue(e, 5))));
+ }
+
+ private IResultTree fetchStaceTrace(ISnapshot snapshot, int objectId) throws Exception {
+ ThreadOverviewQuery query = new ThreadOverviewQuery();
+ query.snapshot = snapshot;
+ query.objects = new IHeapObjectArgument() {
+ @Override
+ public int[] getIds(IProgressListener iProgressListener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getLabel() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<int[]> iterator() {
+ return new Iterator<int[]>() {
+
+ boolean hasNext = true;
+
+ @Override
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ @Override
+ public int[] next() {
+ ASSERT.isTrue(hasNext);
+ hasNext = false;
+ return new int[]{objectId};
+ }
+ };
+ }
+ };
+ return (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ }
+
+ @RouteMeta(path = "/stackTrace")
+ void stackTrace(Future<List<StackFrame>> future, @ParamKey("file") String file,
+ @ParamKey("objectId") int objectId) throws Exception {
+
+
+ IResultTree result = fetchStaceTrace(Analyzer.getOrOpenSnapshotContext(file).getSnapshot(), objectId);
+
+ List<?> elements = result.getElements();
+
+ if (result.hasChildren(elements.get(0))) {
+
+ List<?> frames = result.getChildren(elements.get(0));
+
+ List<StackFrame> res = frames.stream().map(
+ frame -> new StackFrame((String) result.getColumnValue(frame, 0), result.hasChildren(frame)))
+ .collect(Collectors.toList());
+ res.stream().filter(t -> !t.getStack().contains("Native Method")).findFirst()
+ .ifPresent(sf -> sf.setFirstNonNativeFrame(true));
+ future.complete(res);
+ } else {
+ future.complete(Collections.emptyList());
+ }
+ }
+
+ @RouteMeta(path = "/locals")
+ void locals(Future<List<LocalVariable>> future, @ParamKey("file") String file, @ParamKey("objectId") int objectId,
+ @ParamKey("depth") int depth,
+ @ParamKey("firstNonNativeFrame") boolean firstNonNativeFrame) throws Exception {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ IResultTree result = fetchStaceTrace(snapshot, objectId);
+
+ List<?> elements = result.getElements();
+ if (result.hasChildren(elements.get(0))) {
+ List<?> frames = result.getChildren(elements.get(0));
+ Object frame = frames.get(depth - 1);
+ if (result.hasChildren(frame)) {
+ List<?> locals = result.getChildren(frame);
+ future.complete(locals.stream().map(local -> {
+ int id = result.getContext(local).getObjectId();
+ LocalVariable var = new LocalVariable();
+ var.setObjectId(id);
+ try {
+ IObject object = snapshot.getObject(id);
+ var.setLabel(object.getDisplayName());
+ var.setShallowSize(object.getUsedHeapSize());
+ var.setRetainedSize(object.getRetainedHeapSize());
+ var.setObjectType(HeapObject.Type.typeOf(object));
+ var.setGCRoot(snapshot.isGCRoot(id));
+ var.setHasOutbound(result.hasChildren(var));
+ var.setPrefix(Messages.ThreadStackQuery_Label_Local);
+ if (firstNonNativeFrame) {
+ GCRootInfo[] gcRootInfos = object.getGCRootInfo();
+ if (gcRootInfos != null) {
+ for (GCRootInfo gcRootInfo : gcRootInfos) {
+ if (gcRootInfo.getContextId() != 0 &&
+ (gcRootInfo.getType() & GCRootInfo.Type.BUSY_MONITOR) != 0 &&
+ gcRootInfo.getContextId() == objectId) {
+ var.setPrefix(Messages.ThreadStackQuery_Label_Local_Blocked_On);
+ }
+ }
+ }
+ }
+ var.setSuffix(HeapDumpSupport.suffix(snapshot, id));
+ return var;
+ } catch (SnapshotException e) {
+ throw new JifaException(e);
+ }
+ }).collect(Collectors.toList()));
+ return;
+ }
+ }
+ future.complete(Collections.emptyList());
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/UnreachableObjectsRoute.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/UnreachableObjectsRoute.java
new file mode 100644
index 0000000..4f19dc0
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/route/heapdump/UnreachableObjectsRoute.java
@@ -0,0 +1,81 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route.heapdump;
+
+import org.eclipse.jifa.common.request.PagingRequest;
+import org.eclipse.jifa.common.util.PageViewBuilder;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.support.Analyzer;
+import org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport;
+import org.eclipse.jifa.worker.route.ParamKey;
+import org.eclipse.jifa.worker.route.RouteMeta;
+import org.eclipse.jifa.worker.vo.heapdump.unreachable.Record;
+import org.eclipse.jifa.worker.vo.heapdump.unreachable.Summary;
+import io.vertx.core.Future;
+import org.eclipse.mat.query.Bytes;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.UnreachableObjectsHistogram;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+class UnreachableObjectsRoute extends HeapBaseRoute {
+
+ @RouteMeta(path = "/unreachableObjects/summary")
+ void summary(Future<Summary> future, @ParamKey("file") String file) {
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ UnreachableObjectsHistogram histogram = (UnreachableObjectsHistogram) snapshot.getSnapshotInfo().getProperty(
+ UnreachableObjectsHistogram.class.getName());
+
+ Summary summary = new Summary();
+ if (histogram != null) {
+ summary.setTotalSize(histogram.getRowCount());
+ int objects = 0;
+ long shallowSize = 0;
+ for (Object record : histogram.getRecords()) {
+ objects += (Integer) histogram.getColumnValue(record, 1);
+ shallowSize += ((Bytes) histogram.getColumnValue(record, 2)).getValue();
+ }
+
+ summary.setObjects(objects);
+ summary.setShallowSize(shallowSize);
+ }
+ future.complete(summary);
+ }
+
+ @RouteMeta(path = "/unreachableObjects/records")
+ void records(Future<PageView<Record>> future, @ParamKey("file") String file, PagingRequest pagingRequest) {
+
+ ISnapshot snapshot = Analyzer.getOrOpenSnapshotContext(file).getSnapshot();
+ UnreachableObjectsHistogram histogram = (UnreachableObjectsHistogram) snapshot.getSnapshotInfo().getProperty(
+ UnreachableObjectsHistogram.class.getName());
+
+ List<?> total = new ArrayList<>(histogram.getRecords());
+ total.sort((Comparator<Object>) (o1, o2) -> {
+ long v2 = ((Bytes) histogram.getColumnValue(o2, 2)).getValue();
+ long v1 = ((Bytes) histogram.getColumnValue(o1, 2)).getValue();
+ return Long.compare(v2, v1);
+ });
+
+ future.complete(PageViewBuilder.build(total, pagingRequest, record -> {
+ Record r = new Record();
+ r.setClassName((String) histogram.getColumnValue(record, 0));
+ r.setObjectId(HeapDumpSupport.fetchObjectId(histogram.getContext(record)));
+ r.setObjects((Integer) histogram.getColumnValue(record, 1));
+ r.setShallowSize(((Bytes) histogram.getColumnValue(record, 2)).getValue());
+ return r;
+ }));
+
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/AnalysisProgressListener.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/AnalysisProgressListener.java
new file mode 100644
index 0000000..dad633e
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/AnalysisProgressListener.java
@@ -0,0 +1,103 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support;
+
+import org.eclipse.jifa.worker.Constant;
+import org.eclipse.mat.util.IProgressListener;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class AnalysisProgressListener implements IProgressListener {
+
+ private StringBuffer log = new StringBuffer();
+
+ private int total;
+
+ private int done;
+
+ private String lastSubTask;
+
+ private void append(String msg) {
+ log.append(msg);
+ log.append(Constant.LINE_SEPARATOR);
+ }
+
+ public String log() {
+ return log.toString();
+ }
+
+ @Override
+ public void beginTask(String s, int i) {
+ total += i;
+ append(String.format("[Begin task] %s", s));
+ }
+
+ @Override
+ public void done() {
+ }
+
+ @Override
+ public boolean isCanceled() {
+ return false;
+ }
+
+ @Override
+ public void setCanceled(boolean b) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void subTask(String s) {
+ if (lastSubTask == null || !lastSubTask.equals(s)) {
+ lastSubTask = s;
+ append(String.format("[Sub task] %s", s));
+ }
+ }
+
+ @Override
+ public void worked(int i) {
+ done += i;
+ }
+
+ @Override
+ public void sendUserMessage(Severity severity, String s, Throwable throwable) {
+ StringWriter sw = new StringWriter();
+ switch (severity) {
+ case INFO:
+ sw.append("[INFO] ");
+ break;
+ case WARNING:
+ sw.append("[WARNING] ");
+ break;
+ case ERROR:
+ sw.append("[ERROR] ");
+ break;
+ default:
+ sw.append("[UNKNOWN] ");
+ }
+
+ sw.append(s);
+
+ if (throwable != null) {
+ sw.append(Constant.LINE_SEPARATOR);
+ throwable.printStackTrace(new PrintWriter(sw));
+ }
+
+ append(sw.toString());
+ }
+
+ public double percent() {
+ return total == 0 ? 0 : ((double) done) / ((double) total);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/Analyzer.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/Analyzer.java
new file mode 100644
index 0000000..2643b48
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/Analyzer.java
@@ -0,0 +1,226 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import io.vertx.core.Future;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.common.util.ErrorUtil;
+import org.eclipse.jifa.common.util.FileUtil;
+import org.eclipse.jifa.worker.support.heapdump.SnapshotContext;
+import org.eclipse.mat.snapshot.SnapshotFactory;
+import org.eclipse.mat.util.IProgressListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.eclipse.jifa.common.enums.FileType.HEAP_DUMP;
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+import static org.eclipse.jifa.worker.support.heapdump.HeapDumpSupport.VOID_LISTENER;
+
+public class Analyzer {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Analyzer.class);
+
+ private Map<String, AnalysisProgressListener> listeners;
+ private Cache<String, Object> cache;
+
+ private Analyzer() {
+ listeners = new HashMap<>();
+ cache = CacheBuilder.newBuilder().build();
+ }
+
+ private static <T> T getOrBuild(String key, Builder<T> builder) {
+ T result = getInstance().getCacheValueIfPresent(key);
+ if (result != null) {
+ return result;
+ }
+
+ synchronized (key.intern()) {
+ result = getInstance().getCacheValueIfPresent(key);
+ if (result != null) {
+ return result;
+ }
+ try {
+ result = builder.build(key);
+ } catch (Throwable t) {
+ throw new JifaException(t);
+ }
+ getInstance().putCacheValue(key, result);
+ return result;
+ }
+ }
+
+ private static SnapshotContext getOrOpenSnapshotContext(String heapFile,
+ Map<String, String> option, IProgressListener listener) {
+ return getOrBuild(heapFile, key -> new SnapshotContext(
+ SnapshotFactory.openSnapshot(new File(FileSupport.filePath(HEAP_DUMP, heapFile)), option,
+ listener)));
+ }
+
+ public static SnapshotContext getOrOpenSnapshotContext(String heapFile) {
+ return getOrOpenSnapshotContext(heapFile, Collections.emptyMap(), VOID_LISTENER);
+ }
+
+ public static Analyzer getInstance() {
+ return Singleton.INSTANCE;
+ }
+
+ public boolean isFirstAnalysis(FileType fileType, String file) {
+ switch (fileType) {
+ case HEAP_DUMP:
+ return !new File(FileSupport.indexPath(fileType, file)).exists() &&
+ !new File(FileSupport.errorLogPath(fileType, file)).exists() &&
+ getFileListener(file) == null;
+ default:
+ throw new IllegalArgumentException(fileType.name());
+ }
+ }
+
+ public void analyze(Future<Void> future, FileType fileType, String fileName, Map<String, String> options) {
+ AnalysisProgressListener progressListener;
+
+ if (getCacheValueIfPresent(fileName) != null ||
+ new File(FileSupport.errorLogPath(fileType, fileName)).exists()) {
+ future.complete();
+ return;
+ }
+
+ progressListener = new AnalysisProgressListener();
+ boolean success = putFileListener(fileName, progressListener);
+ future.complete();
+
+ if (success) {
+ try {
+ switch (fileType) {
+ case HEAP_DUMP:
+ getOrOpenSnapshotContext(fileName, options, progressListener);
+ break;
+ default:
+ break;
+ }
+ } catch (Exception e) {
+ File log = new File(FileSupport.errorLogPath(fileType, fileName));
+ FileUtil.write(log, progressListener.log(), false);
+ FileUtil.write(log, ErrorUtil.toString(e), true);
+ } finally {
+ removeFileListener(fileName);
+ }
+ }
+ }
+
+ public void clean(FileType fileType, String fileName) {
+ clearCacheValue(fileName);
+
+ File errorLog = new File(FileSupport.errorLogPath(fileType, fileName));
+ if (errorLog.exists()) {
+ ASSERT.isTrue(errorLog.delete(), "Delete error log failed");
+ }
+
+ if (getFileListener(fileName) != null) {
+ return;
+ }
+
+ File index = new File(FileSupport.indexPath(fileType, fileName));
+ if (index.exists()) {
+ ASSERT.isTrue(index.delete(), "Delete index file failed");
+ }
+ }
+
+ public void release(String fileName) {
+ clearCacheValue(fileName);
+ }
+
+ public org.eclipse.jifa.common.vo.Progress pollProgress(FileType fileType, String fileName) {
+ AnalysisProgressListener progressListener = getFileListener(fileName);
+
+ if (progressListener == null) {
+ org.eclipse.jifa.common.vo.Progress progress = buildProgressIfFinished(fileType, fileName);
+ ASSERT.notNull(progress);
+ return progress;
+ } else {
+ org.eclipse.jifa.common.vo.Progress progress = new org.eclipse.jifa.common.vo.Progress();
+ progress.setState(ProgressState.IN_PROGRESS);
+ progress.setMessage(progressListener.log());
+ progress.setPercent(progressListener.percent());
+ return progress;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private synchronized <T> T getCacheValueIfPresent(String key) {
+ return (T) cache.getIfPresent(key);
+ }
+
+ private synchronized void putCacheValue(String key, Object value) {
+ cache.put(key, value);
+ LOGGER.info("Put cache: {}", key);
+ }
+
+ private synchronized void clearCacheValue(String key) {
+ Object value = cache.getIfPresent(key);
+ if (value instanceof SnapshotContext) {
+ SnapshotFactory.dispose(((SnapshotContext) value).getSnapshot());
+ }
+ cache.invalidate(key);
+ LOGGER.info("Clear cache: {}", key);
+ }
+
+ private synchronized AnalysisProgressListener getFileListener(String fileName) {
+ return listeners.get(fileName);
+ }
+
+ private synchronized boolean putFileListener(String fileName, AnalysisProgressListener listener) {
+ if (listeners.containsKey(fileName)) {
+ return false;
+ }
+ listeners.put(fileName, listener);
+ return true;
+ }
+
+ private synchronized void removeFileListener(String fileName) {
+ listeners.remove(fileName);
+ }
+
+ private org.eclipse.jifa.common.vo.Progress buildProgressIfFinished(FileType fileType, String fileName) {
+ if (getCacheValueIfPresent(fileName) != null) {
+ org.eclipse.jifa.common.vo.Progress result = new org.eclipse.jifa.common.vo.Progress();
+ result.setPercent(1);
+ result.setState(ProgressState.SUCCESS);
+ return result;
+ }
+
+ File failed = new File(FileSupport.errorLogPath(fileType, fileName));
+ if (failed.exists()) {
+ org.eclipse.jifa.common.vo.Progress result = new org.eclipse.jifa.common.vo.Progress();
+ result.setState(ProgressState.ERROR);
+ result.setMessage(FileUtil.content(failed));
+ return result;
+ }
+ return null;
+ }
+
+ interface Builder<T> {
+ T build(String key) throws Throwable;
+ }
+
+ private static class Singleton {
+ static Analyzer INSTANCE = new Analyzer();
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/BinFunction.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/BinFunction.java
new file mode 100644
index 0000000..fff47a4
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/BinFunction.java
@@ -0,0 +1,17 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support;
+
+public interface BinFunction<A, B, R> {
+ R apply(A a, B b) throws Exception;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/FileSupport.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/FileSupport.java
new file mode 100644
index 0000000..bdc9727
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/FileSupport.java
@@ -0,0 +1,412 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support;
+
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.event.ProgressEventType;
+import com.aliyun.oss.model.DownloadFileRequest;
+import com.aliyun.oss.model.ObjectMetadata;
+import io.vertx.core.Future;
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.common.StreamCopier;
+import net.schmizz.sshj.xfer.FileSystemFile;
+import net.schmizz.sshj.xfer.scp.SCPDownloadClient;
+import net.schmizz.sshj.xfer.scp.SCPFileTransfer;
+import org.apache.commons.io.FileUtils;
+import org.eclipse.jifa.common.aux.ErrorCode;
+import org.eclipse.jifa.common.aux.JifaException;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.common.util.FileUtil;
+import org.eclipse.jifa.common.vo.FileInfo;
+import org.eclipse.jifa.common.vo.TransferringFile;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.worker.support.heapdump.TransferListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.eclipse.jifa.common.util.Assertion.ASSERT;
+import static org.eclipse.jifa.common.util.GsonHolder.GSON;
+import static org.eclipse.jifa.worker.Constant.File.INFO_FILE_SUFFIX;
+
+public class FileSupport {
+
+ public static final List<String> PUB_KEYS = new ArrayList<>();
+
+ private static final String ERROR_LOG = "error.log";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FileSupport.class);
+
+ private static final Map<String, TransferListener> transferListeners = new ConcurrentHashMap<>();
+
+ private static String[] keyLocations() {
+ final String base = System.getProperty("user.home") + File.separator + ".ssh" + File.separator;
+ return new String[]{base + "jifa-ssh-key"};
+ }
+
+ private static String[] pubKeyLocations() {
+ final String base = System.getProperty("user.home") + File.separator + ".ssh" + File.separator;
+ return new String[]{base + "jifa-ssh-key.pub"};
+ }
+
+ public static void init() {
+ for (FileType type : FileType.values()) {
+ File file = new File(Global.workspace() + File.separator + type.getTag());
+ if (file.exists()) {
+ ASSERT.isTrue(file.isDirectory(), String.format("%s must be directory", file.getAbsolutePath()));
+ } else {
+ ASSERT.isTrue(file.mkdirs(), String.format("Can not create %s ", file.getAbsolutePath()));
+ }
+ }
+
+ for (String loc : pubKeyLocations()) {
+ File f = new File(loc);
+ if (f.exists() && f.length() > 0) {
+ PUB_KEYS.add(FileUtil.content(f));
+ }
+ }
+ }
+
+ public static void initInfoFile(FileType type, String originalName, String name) {
+ ASSERT.isTrue(new File(dirPath(type, name)).mkdirs(), "Make directory failed");
+
+ FileInfo info = buildInitFileInfo(type, originalName, name);
+ try {
+ FileUtils.write(infoFile(type, name), GSON.toJson(info), Charset.defaultCharset());
+ } catch (IOException e) {
+ LOGGER.error("Write file information failed", e);
+ throw new JifaException(e);
+ }
+ }
+
+ private static FileInfo buildInitFileInfo(FileType type, String originalName, String name) {
+ FileInfo info = new FileInfo();
+ info.setOriginalName(originalName);
+ info.setName(name);
+ info.setSize(0);
+ info.setType(type);
+ info.setTransferState(ProgressState.NOT_STARTED);
+ info.setDownloadable(false);
+ info.setCreationTime(System.currentTimeMillis());
+ return info;
+ }
+
+ public static List<FileInfo> info(FileType type) {
+ List<FileInfo> infoList = new ArrayList<>();
+ File dir = new File(dirPath(type));
+ ASSERT.isTrue(dir.isDirectory(), ErrorCode.SANITY_CHECK);
+
+ File[] subDirs = dir.listFiles(File::isDirectory);
+ if (subDirs == null) {
+ return infoList;
+ }
+
+ for (File subDir : subDirs) {
+ String infoFileName = subDir.getName() + INFO_FILE_SUFFIX;
+ File[] files = subDir.listFiles((d, name) -> infoFileName.equals(name));
+ if (files != null && files.length == 1) {
+ File infoFile = files[0];
+ try {
+ FileInfo info = GSON.fromJson(FileUtils.readFileToString(infoFile, Charset.defaultCharset()),
+ FileInfo.class);
+ ensureValidFileInfo(info);
+ infoList.add(info);
+ } catch (Exception e) {
+ LOGGER.error("Read file information failed: {}", infoFile.getAbsolutePath(), e);
+ // should not throw exception here
+ }
+ }
+ }
+ return infoList;
+ }
+
+ private static void ensureValidFileInfo(FileInfo info) {
+ ASSERT.notNull(info)
+ .notNull(info.getOriginalName())
+ .notNull(info.getName())
+ .notNull(info.getType())
+ .notNull(info.getTransferState())
+ .isTrue(info.getSize() >= 0)
+ .isTrue(info.getCreationTime() > 0);
+ }
+
+ public static FileInfo getOrGenInfo(FileType type, String name) {
+ File file = new File(FileSupport.filePath(type, name));
+ ASSERT.isTrue(file.exists(), ErrorCode.FILE_DOES_NOT_EXIST);
+
+ File infoFile = infoFile(type, name);
+ if (infoFile.exists()) {
+ return info(type, name);
+ }
+
+ FileInfo fileInfo = buildInitFileInfo(type, name, name);
+ fileInfo.setCreationTime(file.lastModified());
+ fileInfo.setTransferState(ProgressState.SUCCESS);
+ fileInfo.setSize(file.length());
+ save(fileInfo);
+ return fileInfo;
+ }
+
+ public static FileInfo info(FileType type, String name) {
+ File infoFile = infoFile(type, name);
+ FileInfo fileInfo;
+ try {
+ fileInfo = GSON.fromJson(FileUtils.readFileToString(infoFile, Charset.defaultCharset()), FileInfo.class);
+ ensureValidFileInfo(fileInfo);
+ } catch (IOException e) {
+ LOGGER.error("Read file information failed", e);
+ throw new JifaException(e);
+ }
+ return fileInfo;
+ }
+
+ public static void save(FileInfo info) {
+ try {
+ FileUtils
+ .write(infoFile(info.getType(), info.getName()), GSON.toJson(info), Charset.defaultCharset());
+ } catch (IOException e) {
+ LOGGER.error("Save file information failed", e);
+ throw new JifaException(e);
+ }
+ }
+
+ public static void delete(FileType type, String name) {
+ try {
+ FileUtils.deleteDirectory(new File(dirPath(type, name)));
+ } catch (IOException e) {
+ LOGGER.error("Delete file failed", e);
+ throw new JifaException(e);
+ }
+ }
+
+ public static void updateTransferState(FileType type, String name, ProgressState state) {
+ FileInfo info = info(type, name);
+ info.setTransferState(state);
+ if (state == ProgressState.SUCCESS) {
+ // for worker, file is downloadable after transferred
+ info.setSize(new File(FileSupport.filePath(type, name)).length());
+ info.setDownloadable(true);
+ }
+ save(info);
+ }
+
+ private static String dirPath(FileType type) {
+ return Global.workspace() + File.separator + type.getTag();
+ }
+
+ public static String dirPath(FileType type, String name) {
+ return dirPath(type) + File.separator + name;
+ }
+
+ private static String infoFilePath(FileType type, String name) {
+ return dirPath(type, name) + File.separator + name + INFO_FILE_SUFFIX;
+ }
+
+ private static File infoFile(FileType type, String name) {
+ return new File(infoFilePath(type, name));
+ }
+
+ public static String filePath(FileType type, String name) {
+ return filePath(type, name, name);
+ }
+
+ private static String filePath(FileType type, String name, String childrenName) {
+ return dirPath(type, name) + File.separator + childrenName;
+ }
+
+ public static String errorLogPath(FileType fileType, String file) {
+ return FileSupport.filePath(fileType, file, ERROR_LOG);
+ }
+
+ public static String indexPath(FileType fileType, String file) {
+ String indexFileNamePrefix;
+ int i = file.lastIndexOf('.');
+ if (i >= 0) {
+ indexFileNamePrefix = file.substring(0, i + 1);
+ } else {
+ indexFileNamePrefix = file + '.';
+ }
+ return FileSupport.filePath(fileType, file, indexFileNamePrefix + "index");
+ }
+
+ public static TransferListener createTransferListener(FileType fileType, String originalName, String fileName) {
+ TransferListener listener = new TransferListener(fileType, originalName, fileName);
+ transferListeners.put(fileName, listener);
+ return listener;
+ }
+
+ public static void removeTransferListener(String fileName) {
+ transferListeners.remove(fileName);
+ }
+
+ public static TransferListener getTransferListener(String fileName) {
+ return transferListeners.get(fileName);
+ }
+
+ public static void transferBySCP(String user, String hostname, String src, FileType fileType, String fileName,
+ TransferListener transferProgressListener, Future<TransferringFile> future) {
+ transferBySCP(user, null, hostname, src, fileType, fileName, transferProgressListener, future);
+ }
+
+ public static void transferBySCP(String user, String pwd, String hostname, String src, FileType fileType,
+ String fileName, TransferListener transferProgressListener,
+ Future<TransferringFile> future) {
+ transferProgressListener.updateState(ProgressState.IN_PROGRESS);
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier((h, port, key) -> true);
+ try {
+ ssh.connect(hostname);
+ if (pwd != null) {
+ ssh.authPassword(user, pwd);
+ } else {
+ ssh.authPublickey(user, keyLocations());
+ }
+ SCPFileTransfer transfer = ssh.newSCPFileTransfer();
+ transfer.setTransferListener(new net.schmizz.sshj.xfer.TransferListener() {
+ @Override
+ public net.schmizz.sshj.xfer.TransferListener directory(String name) {
+ return this;
+ }
+
+ @Override
+ public StreamCopier.Listener file(String name, long size) {
+ transferProgressListener.setTotalSize(size);
+ return transferProgressListener::setTransferredSize;
+ }
+ });
+ SCPDownloadClient downloadClient = transfer.newSCPDownloadClient();
+ future.complete(new TransferringFile(fileName));
+ // do not copy dir now
+ downloadClient.setRecursiveMode(false);
+ downloadClient.copy(src, new FileSystemFile(FileSupport.filePath(fileType, fileName)));
+ transferProgressListener.updateState(ProgressState.SUCCESS);
+ } catch (Exception e) {
+ LOGGER.error("SSH transfer failed");
+ handleTransferError(fileName, transferProgressListener, future, e);
+ } finally {
+ try {
+ ssh.disconnect();
+ } catch (IOException e) {
+ LOGGER.error("SSH disconnect failed", e);
+ }
+ }
+ }
+
+ public static void transferByURL(String url, FileType fileType, String fileName, TransferListener listener,
+ Future<TransferringFile> future) {
+ InputStream in = null;
+ OutputStream out = null;
+ String filePath = FileSupport.filePath(fileType, fileName);
+ try {
+ URLConnection conn = new URL(url).openConnection();
+ listener.updateState(ProgressState.IN_PROGRESS);
+ future.complete(new TransferringFile(fileName));
+ listener.setTotalSize(conn.getContentLength());
+ in = conn.getInputStream();
+ out = new FileOutputStream(filePath);
+ byte[] buffer = new byte[8192];
+ int length;
+ while ((length = in.read(buffer)) > 0) {
+ out.write(buffer, 0, length);
+ listener.addTransferredSize(length);
+ }
+ listener.updateState(ProgressState.SUCCESS);
+ } catch (Exception e) {
+ LOGGER.error("URL transfer failed");
+ handleTransferError(fileName, listener, future, e);
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ } catch (IOException e) {
+ LOGGER.error("Close stream failed", e);
+ }
+ }
+ }
+
+ public static void transferByOSS(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
+ String objectName, FileType fileType, String fileName,
+ TransferListener transferProgressListener,
+ Future<TransferringFile> future) {
+ OSSClient ossClient = null;
+ try {
+ ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
+
+ ObjectMetadata meta = ossClient.getObjectMetadata(bucketName, objectName);
+ transferProgressListener.setTotalSize(meta.getContentLength());
+ future.complete(new TransferringFile(fileName));
+
+ DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucketName, objectName);
+ downloadFileRequest.setDownloadFile(new File(FileSupport.filePath(fileType, fileName)).getAbsolutePath());
+ // 128m per thread now
+ downloadFileRequest.setPartSize(128 * 1024 * 1024);
+ downloadFileRequest.setTaskNum(Runtime.getRuntime().availableProcessors());
+ downloadFileRequest.setEnableCheckpoint(true);
+ downloadFileRequest.withProgressListener(progressEvent -> {
+ long bytes = progressEvent.getBytes();
+ ProgressEventType eventType = progressEvent.getEventType();
+ switch (eventType) {
+ case TRANSFER_STARTED_EVENT:
+ transferProgressListener.updateState(ProgressState.IN_PROGRESS);
+ break;
+ case RESPONSE_BYTE_TRANSFER_EVENT:
+ transferProgressListener.addTransferredSize(bytes);
+ break;
+ case TRANSFER_FAILED_EVENT:
+ transferProgressListener.updateState(ProgressState.ERROR);
+ break;
+ default:
+ break;
+ }
+ });
+ ossClient.downloadFile(downloadFileRequest);
+ transferProgressListener.updateState(ProgressState.SUCCESS);
+ } catch (Throwable t) {
+ LOGGER.error("OSS transfer failed");
+ handleTransferError(fileName, transferProgressListener, future, t);
+ } finally {
+ if (ossClient != null) {
+ ossClient.shutdown();
+ }
+ }
+ }
+
+ private static void handleTransferError(String fileName, TransferListener transferProgressListener,
+ Future<TransferringFile> future, Throwable t) {
+ if (future.isComplete()) {
+ transferProgressListener.updateState(ProgressState.ERROR);
+ Throwable cause = t;
+ while (cause.getCause() != null) {
+ cause = cause.getCause();
+ }
+ transferProgressListener.setErrorMsg(cause.toString());
+ } else {
+ FileSupport.delete(transferProgressListener.getFileType(), fileName);
+ removeTransferListener(fileName);
+ }
+ throw new JifaException(ErrorCode.TRANSFER_ERROR, t);
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/HeapDumpSupport.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/HeapDumpSupport.java
new file mode 100644
index 0000000..3c069b8
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/HeapDumpSupport.java
@@ -0,0 +1,85 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support.heapdump;
+
+import org.eclipse.mat.SnapshotException;
+import org.eclipse.mat.query.IContextObject;
+import org.eclipse.mat.snapshot.ISnapshot;
+import org.eclipse.mat.snapshot.model.GCRootInfo;
+import org.eclipse.mat.snapshot.model.IObject;
+import org.eclipse.mat.snapshot.model.NamedReference;
+import org.eclipse.mat.snapshot.query.IHeapObjectArgument;
+import org.eclipse.mat.util.IProgressListener;
+import org.eclipse.mat.util.VoidProgressListener;
+
+import java.util.Iterator;
+import java.util.List;
+
+import static org.eclipse.jifa.common.Constant.EMPTY_STRING;
+
+public class HeapDumpSupport {
+ public static final int ILLEGAL_OBJECT_ID = -1;
+
+ public static IProgressListener VOID_LISTENER = new VoidProgressListener();
+
+ public static int fetchObjectId(IContextObject context) {
+ return context == null ? ILLEGAL_OBJECT_ID : context.getObjectId();
+ }
+
+ public static String suffix(ISnapshot snapshot, int objectId) throws SnapshotException {
+ GCRootInfo[] gc = snapshot.getGCRootInfo(objectId);
+ return gc != null ? GCRootInfo.getTypeSetAsString(gc) : EMPTY_STRING;
+ }
+
+ public static String suffix(GCRootInfo[] gcRootInfo) {
+ return gcRootInfo != null ? GCRootInfo.getTypeSetAsString(gcRootInfo) : EMPTY_STRING;
+ }
+
+ public static String prefix(ISnapshot snapshot, int objectId, int outbound) throws SnapshotException {
+ IObject object = snapshot.getObject(objectId);
+
+ long address = snapshot.mapIdToAddress(outbound);
+
+ StringBuilder s = new StringBuilder(64);
+
+ List<NamedReference> refs = object.getOutboundReferences();
+ for (NamedReference reference : refs) {
+ if (reference.getObjectAddress() == address) {
+ if (s.length() > 0) {
+ s.append(", ");
+ }
+ s.append(reference.getName());
+ }
+ }
+ return s.toString();
+ }
+
+ public static IHeapObjectArgument buildHeapObjectArgument(int[] ids) {
+ return new IHeapObjectArgument() {
+ @Override
+ public int[] getIds(IProgressListener iProgressListener) {
+ return ids;
+ }
+
+ @Override
+ public String getLabel() {
+ return null;
+ }
+
+ @Override
+ public Iterator<int[]> iterator() {
+ return null;
+ }
+ };
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/SnapshotContext.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/SnapshotContext.java
new file mode 100644
index 0000000..7735103
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/SnapshotContext.java
@@ -0,0 +1,199 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support.heapdump;
+
+import lombok.Data;
+import org.eclipse.mat.inspections.ClassLoaderExplorerQuery;
+import org.eclipse.mat.inspections.LeakHunterQuery;
+import org.eclipse.mat.inspections.OQLQuery;
+import org.eclipse.mat.internal.snapshot.SnapshotQueryContext;
+import org.eclipse.mat.internal.snapshot.inspections.OldObjRefYoungObjQuery;
+import org.eclipse.mat.query.Column;
+import org.eclipse.mat.query.IResult;
+import org.eclipse.mat.query.IResultTable;
+import org.eclipse.mat.query.IResultTree;
+import org.eclipse.mat.query.refined.RefinedResultBuilder;
+import org.eclipse.mat.query.refined.RefinedTable;
+import org.eclipse.mat.snapshot.ISnapshot;
+
+import java.lang.ref.SoftReference;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SnapshotContext {
+
+ private ISnapshot snapshot;
+
+ private SoftReference<DirectByteBuffer> directByteBuffer;
+ private SoftReference<ClassLoaderExplorer> classLoaderExplorer;
+ private SoftReference<LeakReport> leakReport;
+
+ public SnapshotContext(ISnapshot snapshot) {
+ this.snapshot = snapshot;
+ }
+
+ private synchronized <T> T fetch(SoftReference<T> cache, Builder<T> builder) throws Exception {
+ T res;
+ if (cache == null || (res = cache.get()) == null) {
+ res = builder.build();
+ }
+ return res;
+ }
+
+ public synchronized ClassLoaderExplorer classLoaderExplorer() throws Exception {
+ return fetch(classLoaderExplorer, () -> {
+ ClassLoaderExplorer result = new ClassLoaderExplorer();
+ classLoaderExplorer = new SoftReference<>(result);
+ return result;
+ });
+ }
+
+ public synchronized DirectByteBuffer directByteBuffer() throws Exception {
+ return fetch(directByteBuffer, () -> {
+ DirectByteBuffer result = new DirectByteBuffer();
+ directByteBuffer = new SoftReference<>(result);
+ return result;
+ });
+ }
+
+ public synchronized LeakReport leakReport() throws Exception {
+ return fetch(leakReport, () -> {
+ LeakReport result = new LeakReport();
+ leakReport = new SoftReference<>(result);
+ return result;
+ });
+ }
+
+ public ISnapshot getSnapshot() {
+ return snapshot;
+ }
+
+ interface Builder<T> {
+ T build() throws Exception;
+ }
+
+ @Data
+ public class LeakReport {
+ IResult result;
+
+ LeakReport() throws Exception {
+ LeakHunterQuery query = new LeakHunterQuery();
+ query.snapshot = snapshot;
+ result = query.execute(HeapDumpSupport.VOID_LISTENER);
+ }
+ }
+
+ @Data
+ public class DirectByteBuffer {
+ private static final String OQL =
+ "SELECT s.@displayName as label, s.position as position, s.limit as limit, s.capacity as " +
+ "capacity FROM java.nio.DirectByteBuffer s where s.cleaner != null";
+ RefinedTable resultContext;
+ private long position;
+ private long limit;
+ private long capacity;
+ private int totalSize;
+
+ DirectByteBuffer() throws Exception {
+ OQLQuery query = new OQLQuery();
+ query.snapshot = snapshot;
+ query.queryString = OQL;
+ IResult result = query.execute(HeapDumpSupport.VOID_LISTENER);
+ if (result instanceof IResultTable) {
+ RefinedResultBuilder builder =
+ new RefinedResultBuilder(new SnapshotQueryContext(snapshot), (IResultTable) result);
+ builder.setSortOrder(3, Column.SortDirection.DESC);
+ resultContext = (RefinedTable) builder.build();
+ totalSize = resultContext.getRowCount();
+ for (int i = 0; i < totalSize; i++) {
+ Object row = resultContext.getRow(i);
+ position += position(row);
+ limit += limit(row);
+ capacity += capacity(row);
+ }
+ }
+
+ }
+
+ public String label(Object row) {
+ return (String) resultContext.getColumnValue(row, 0);
+ }
+
+ public int position(Object row) {
+ return (Integer) resultContext.getColumnValue(row, 1);
+ }
+
+ public int limit(Object row) {
+ return (Integer) resultContext.getColumnValue(row, 2);
+ }
+
+ public int capacity(Object row) {
+ return (Integer) resultContext.getColumnValue(row, 3);
+ }
+
+ }
+
+ @Data
+ public class OldObjRefYoungObj {
+ private OldObjRefYoungObjQuery.Tree result;
+ private List<?> records;
+ private int refCount;
+
+ OldObjRefYoungObj() throws Exception {
+ OldObjRefYoungObjQuery query = new OldObjRefYoungObjQuery();
+ query.snapshot = snapshot;
+ query.groupBy = OldObjRefYoungObjQuery.Grouping.BY_CLASS;
+ result = query.execute(HeapDumpSupport.VOID_LISTENER);
+ records = result.getElements();
+ for (Object record : records) {
+ refCount += (int) result.getColumnValue(record, 1);
+ }
+ }
+ }
+
+ @Data
+ public class ClassLoaderExplorer {
+ private IResult resultContext;
+
+ // classloader object Id -> record
+ private Map<Integer, Object> classLoaderIdMap;
+
+ private List<?> records;
+
+ private int definedClasses;
+
+ private int numberOfInstances;
+
+ ClassLoaderExplorer() throws Exception {
+ ClassLoaderExplorerQuery query = new ClassLoaderExplorerQuery();
+ query.snapshot = snapshot;
+ IResultTree result = (IResultTree) query.execute(HeapDumpSupport.VOID_LISTENER);
+ this.resultContext = result;
+ Map<Integer, Object> classLoaderIdMap = new HashMap<>();
+ for (Object r : result.getElements()) {
+ classLoaderIdMap.put(result.getContext(r).getObjectId(), r);
+ }
+ this.records = result.getElements();
+ this.records.sort((Comparator<Object>) (o1, o2) -> Integer
+ .compare((int) result.getColumnValue(o2, 1), (int) result.getColumnValue(o1, 1)));
+ this.classLoaderIdMap = classLoaderIdMap;
+
+ for (Object record : records) {
+ definedClasses += (int) result.getColumnValue(record, 1);
+ numberOfInstances += (int) result.getColumnValue(record, 2);
+ }
+ }
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/TransferListener.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/TransferListener.java
new file mode 100644
index 0000000..60f28b9
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/support/heapdump/TransferListener.java
@@ -0,0 +1,62 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.support.heapdump;
+
+import lombok.Data;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.worker.support.FileSupport;
+
+@Data
+public class TransferListener {
+
+ private ProgressState state;
+ private long totalSize;
+ private long transferredSize;
+ private String errorMsg;
+
+ private FileType fileType;
+ private String fileName;
+
+ public TransferListener(FileType fileType, String originalName, String fileName) {
+ this.fileType = fileType;
+ this.fileName = fileName;
+ this.state = ProgressState.NOT_STARTED;
+ FileSupport.initInfoFile(fileType, originalName, fileName);
+ }
+
+ public synchronized void updateState(ProgressState state) {
+ if (this.state == state) {
+ return;
+ }
+
+ if (state == ProgressState.SUCCESS) {
+ FileSupport.updateTransferState(fileType, fileName, ProgressState.SUCCESS);
+ totalSize = FileSupport.info(fileType, fileName).getSize();
+ }
+
+ if (state == ProgressState.ERROR) {
+ FileSupport.updateTransferState(fileType, fileName, ProgressState.ERROR);
+ }
+
+ if (state == ProgressState.IN_PROGRESS && this.state == ProgressState.NOT_STARTED) {
+ FileSupport.updateTransferState(fileType, fileName, ProgressState.IN_PROGRESS);
+ }
+
+ this.state = state;
+ }
+
+ public synchronized void addTransferredSize(long bytes) {
+ this.transferredSize += bytes;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/HeapObject.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/HeapObject.java
new file mode 100644
index 0000000..c42c7d5
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/HeapObject.java
@@ -0,0 +1,57 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump;
+
+import lombok.Data;
+import org.eclipse.mat.snapshot.model.IClass;
+import org.eclipse.mat.snapshot.model.IClassLoader;
+import org.eclipse.mat.snapshot.model.IObject;
+
+@Data
+public class HeapObject {
+ private int objectId;
+ private String prefix;
+ private String label;
+ private String suffix;
+ private long shallowSize;
+ private long retainedSize;
+ private boolean hasInbound;
+ private boolean hasOutbound;
+ private int objectType;
+ private boolean gCRoot;
+
+ public static class Type {
+
+ static final int CLASS = 1;
+ static final int CLASS_LOADER = 2;
+ static final int ARRAY = 3;
+ static final int NORMAL = 4;
+
+ public static int typeOf(IObject object) {
+ if (object instanceof IClass) {
+ return CLASS;
+ }
+
+ if (object instanceof IClassLoader) {
+ return CLASS_LOADER;
+ }
+
+ if (object.getClazz().isArrayType()) {
+ return ARRAY;
+ }
+ return NORMAL;
+ }
+ }
+}
+
+
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Record.java
new file mode 100644
index 0000000..328d65d
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Record.java
@@ -0,0 +1,33 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.classloader;
+
+import lombok.Data;
+
+@Data
+public class Record {
+
+ private int objectId;
+
+ private String prefix;
+
+ private String label;
+
+ private boolean classLoader;
+
+ private boolean hasParent;
+
+ private int definedClasses;
+
+ private int numberOfInstances;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Summary.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Summary.java
new file mode 100644
index 0000000..1e84862
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classloader/Summary.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.classloader;
+
+import lombok.Data;
+
+@Data
+public class Summary {
+
+ private int totalSize;
+
+ private int definedClasses;
+
+ private int numberOfInstances;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classreference/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classreference/Record.java
new file mode 100644
index 0000000..ea08de8
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/classreference/Record.java
@@ -0,0 +1,31 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.classreference;
+
+import lombok.Data;
+
+@Data
+public class Record {
+
+ private String label;
+
+ private int objects;
+
+ private long shallowSize;
+
+ private int objectId;
+
+ private int[] objectIds;
+
+ private int type;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Record.java
new file mode 100644
index 0000000..5020c1f
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Record.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.compare;
+
+import lombok.Data;
+
+@Data
+public class Record {
+
+ private String className;
+
+ private long objects;
+
+ private long shallowSize;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Summary.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Summary.java
new file mode 100644
index 0000000..252fd63
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/compare/Summary.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.compare;
+
+import lombok.Data;
+
+@Data
+public class Summary {
+
+ private int totalSize;
+
+ private long objects;
+
+ private long shallowSize;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Record.java
new file mode 100644
index 0000000..e063652
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Record.java
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.directbytebuffer;
+
+import lombok.Data;
+
+@Data
+public class Record {
+
+ private int objectId;
+
+ private String label;
+
+ private int position;
+
+ private int limit;
+
+ private int capacity;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Summary.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Summary.java
new file mode 100644
index 0000000..2641e82
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/directbytebuffer/Summary.java
@@ -0,0 +1,27 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.directbytebuffer;
+
+import lombok.Data;
+
+@Data
+public class Summary {
+
+ private int totalSize;
+
+ private long position;
+
+ private long limit;
+
+ private long capacity;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/BaseRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/BaseRecord.java
new file mode 100644
index 0000000..3afc504
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/BaseRecord.java
@@ -0,0 +1,35 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.dominatortree;
+
+import lombok.Data;
+
+@Data
+public class BaseRecord {
+
+ private String label;
+
+ private String suffix;
+
+ private int objectId;
+
+ private int objectType;
+
+ private boolean gCRoot;
+
+ private long shallowSize;
+
+ private long retainedSize;
+
+ private double percent;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassLoaderRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassLoaderRecord.java
new file mode 100644
index 0000000..885e924
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassLoaderRecord.java
@@ -0,0 +1,22 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.dominatortree;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ClassLoaderRecord extends BaseRecord {
+ private long objects;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassRecord.java
new file mode 100644
index 0000000..7d9a848
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/ClassRecord.java
@@ -0,0 +1,22 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.dominatortree;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ClassRecord extends BaseRecord {
+ private int objects;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/DefaultRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/DefaultRecord.java
new file mode 100644
index 0000000..d068f99
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/DefaultRecord.java
@@ -0,0 +1,21 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.dominatortree;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DefaultRecord extends BaseRecord {
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/PackageRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/PackageRecord.java
new file mode 100644
index 0000000..186ea1d
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/dominatortree/PackageRecord.java
@@ -0,0 +1,20 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.dominatortree;
+
+import lombok.Data;
+
+@Data
+public class PackageRecord {
+ private long objects;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassLoaderRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassLoaderRecord.java
new file mode 100644
index 0000000..55cc64f
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassLoaderRecord.java
@@ -0,0 +1,31 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.duplicatedclass;
+
+import lombok.Data;
+
+@Data
+public class ClassLoaderRecord {
+
+ private String label;
+
+ private String suffix;
+
+ private int definedClassesCount;
+
+ private int instantiatedObjectsCount;
+
+ private int objectId;
+
+ private boolean gCRoot;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassRecord.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassRecord.java
new file mode 100644
index 0000000..2487302
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/duplicatedclass/ClassRecord.java
@@ -0,0 +1,23 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.duplicatedclass;
+
+import lombok.Data;
+
+@Data
+public class ClassRecord {
+
+ private String label;
+
+ private int count;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcroot/Result.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcroot/Result.java
new file mode 100644
index 0000000..b163911
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcroot/Result.java
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.gcroot;
+
+import lombok.Data;
+
+@Data
+public class Result {
+
+ private String className;
+
+ private int objects;
+
+ private int objectId;
+
+ private long shallowSize;
+
+ private long retainedSize;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcrootpath/Result.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcrootpath/Result.java
new file mode 100644
index 0000000..86e8dee
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/gcrootpath/Result.java
@@ -0,0 +1,50 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.gcrootpath;
+
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class Result {
+
+ private Node tree;
+ private int count;
+ private boolean hasMore;
+
+ @Data
+ @EqualsAndHashCode(callSuper = true)
+ public static class Node extends HeapObject {
+
+ private boolean origin;
+
+ private List<Node> children = new ArrayList<>();
+
+ public void addChild(Node child) {
+ children.add(child);
+ }
+
+ public Node getChild(int objectId) {
+ for (Node child : children) {
+ if (child.getObjectId() == objectId) {
+ return child;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/histogram/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/histogram/Record.java
new file mode 100644
index 0000000..0ba0902
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/histogram/Record.java
@@ -0,0 +1,52 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.histogram;
+
+import lombok.Data;
+
+@Data
+public class Record {
+ private long numberOfObjects;
+ private long shallowSize;
+ private long numberOfYoungObjects;
+ private long shallowSizeOfYoung;
+ private long numberOfOldObjects;
+ private long shallowSizeOfOld;
+ private long retainedSize;
+ private String label;
+ private int objectId;
+
+ private int type;
+
+ public Record(int objectId, String label, int type, long numberOfObjects, long shallowSize, long retainedSize,
+ long numberOfYoungObjects, long shallowSizeOfYoung, long numberOfOldObjects, long shallowSizeOfOld) {
+ this.objectId = objectId;
+ this.label = label;
+ this.type = type;
+ this.numberOfObjects = numberOfObjects;
+ this.shallowSize = shallowSize;
+ this.retainedSize = retainedSize;
+
+ this.numberOfYoungObjects = numberOfYoungObjects;
+ this.shallowSizeOfYoung = shallowSizeOfYoung;
+ this.numberOfOldObjects = numberOfOldObjects;
+ this.shallowSizeOfOld = shallowSizeOfOld;
+ }
+
+ public static class Type {
+ public static int CLASS = 1;
+ public static int SUPER_CLASS = 2;
+ public static int CLASS_LOADER = 3;
+ public static int PACKAGE = 4;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/FieldView.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/FieldView.java
new file mode 100644
index 0000000..b32b24e
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/FieldView.java
@@ -0,0 +1,45 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.inspector;
+
+import lombok.Data;
+
+@Data
+public class FieldView {
+
+ /**
+ * @see org.eclipse.mat.snapshot.model.IObject.Type
+ */
+ private int fieldType;
+
+ private String name;
+
+ private String value;
+
+ private int objectId;
+
+ public FieldView(int fieldType, String name, String value) {
+ this.fieldType = fieldType;
+ this.name = name;
+ this.value = value;
+ }
+
+ public FieldView(int fieldType, String name, String value, int objectId) {
+ this(fieldType, name, value);
+ this.objectId = objectId;
+ }
+
+ public FieldView() {
+
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/ObjectView.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/ObjectView.java
new file mode 100644
index 0000000..0a1d9ea
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/inspector/ObjectView.java
@@ -0,0 +1,63 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.inspector;
+
+import lombok.Data;
+import org.eclipse.mat.snapshot.model.HeapLayout;
+
+@Data
+public class ObjectView {
+
+ private long objectAddress;
+
+ /**
+ * for non-class object, name = the name of object's class
+ * for class object, name = class name
+ */
+ private String name;
+
+ private boolean gCRoot;
+
+ private int objectType;
+
+ private String classLabel;
+
+ private boolean classGCRoot;
+
+ private String superClassName;
+
+ private String classLoaderLabel;
+
+ private boolean classLoaderGCRoot;
+
+ private long shallowSize;
+
+ private long retainedSize;
+
+ private String gcRootInfo;
+
+ private int locationType;
+
+ private static final int YOUNG = 1;
+ private static final int OLD = 2;
+ private static final int OTHER = 0;
+
+ public static int locationTypeOf(HeapLayout.Generation gen) {
+ if (gen == HeapLayout.Generation.YOUNG) {
+ return YOUNG;
+ } else if (gen == HeapLayout.Generation.OLD) {
+ return OLD;
+ }
+ return OTHER;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/leak/Report.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/leak/Report.java
new file mode 100644
index 0000000..a22a277
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/leak/Report.java
@@ -0,0 +1,81 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.leak;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Report {
+
+ private boolean useful;
+
+ private String info;
+
+ private String name;
+
+ private List<Slice> slices;
+
+ private List<Record> records;
+
+ @Data
+ public static class Slice {
+
+ private String label;
+
+ private int objectId;
+
+ private double value;
+
+ private String desc;
+
+ public Slice(String label, int objectId, double value, String desc) {
+ this.label = label;
+ this.objectId = objectId;
+ this.value = value;
+ this.desc = desc;
+ }
+ }
+
+ @Data
+ public static class Record {
+
+ private String name;
+
+ private String desc;
+
+ private int index;
+
+ private List<ShortestPath> paths;
+ }
+
+ @Data
+ public static class ShortestPath {
+
+ private String label;
+
+ private long shallowSize;
+
+ private long retainedSize;
+
+ private int objectId;
+
+ private int objectType;
+
+ private boolean gCRoot;
+
+ private List<ShortestPath> children;
+ }
+}
+
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/OQLResult.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/OQLResult.java
new file mode 100644
index 0000000..ec896a3
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/OQLResult.java
@@ -0,0 +1,21 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.oql;
+
+interface OQLResult {
+ int TREE = 1;
+ int TABLE = 2;
+ int TEXT = 3;
+
+ int getType();
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TableResult.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TableResult.java
new file mode 100644
index 0000000..6b53b53
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TableResult.java
@@ -0,0 +1,45 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.oql;
+
+import org.eclipse.jifa.common.vo.PageView;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TableResult implements OQLResult {
+ private int type = TABLE;
+
+ private List<String> columns;
+
+ private PageView<Entry> pv;
+
+ public TableResult(List<String> columns, PageView<Entry> pv) {
+ this.columns = columns;
+ this.pv = pv;
+ }
+
+ @Data
+ public static class Entry {
+
+ private int objectId;
+
+ private List<Object> values;
+
+ public Entry(int objectId, List<Object> values) {
+ this.objectId = objectId;
+ this.values = values;
+ }
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TextResult.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TextResult.java
new file mode 100644
index 0000000..3eb067c
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TextResult.java
@@ -0,0 +1,26 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.oql;
+
+import lombok.Data;
+
+@Data
+public class TextResult implements OQLResult {
+ private int type = OQLResult.TEXT;
+
+ private String text;
+
+ public TextResult(String text) {
+ this.text = text;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TreeResult.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TreeResult.java
new file mode 100644
index 0000000..1589767
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/oql/TreeResult.java
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.oql;
+
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import lombok.Data;
+
+@Data
+public class TreeResult implements OQLResult {
+
+ PageView<HeapObject> pv;
+
+ private int type = TREE;
+
+ public TreeResult(PageView<HeapObject> pv) {
+ this.pv = pv;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/BigObject.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/BigObject.java
new file mode 100644
index 0000000..2f5da72
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/BigObject.java
@@ -0,0 +1,34 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.overview;
+
+import lombok.Data;
+
+@Data
+public class BigObject {
+
+ private String label;
+
+ private int objectId;
+
+ private double value;
+
+ private String description;
+
+ public BigObject(String label, int objectId, double value, String description) {
+ this.label = label;
+ this.objectId = objectId;
+ this.value = value;
+ this.description = description;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/Details.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/Details.java
new file mode 100644
index 0000000..5cec709
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/overview/Details.java
@@ -0,0 +1,41 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.overview;
+
+import lombok.Data;
+
+@Data
+public class Details {
+ private String jvmInfo;
+ private int identifierSize;
+ private long creationDate;
+ private int numberOfObjects;
+ private int numberOfGCRoots;
+ private int numberOfClasses;
+ private int numberOfClassLoaders;
+ private long usedHeapSize;
+ private boolean generationInfoAvailable;
+
+ public Details(String jvmInfo, int identifierSize, long creationDate, int numberOfObjects, int numberOfGCRoots,
+ int numberOfClasses, int numberOfClassLoaders, long usedHeapSize, boolean generationInfoAvailable) {
+ this.jvmInfo = jvmInfo;
+ this.identifierSize = identifierSize;
+ this.creationDate = creationDate;
+ this.numberOfObjects = numberOfObjects;
+ this.numberOfGCRoots = numberOfGCRoots;
+ this.numberOfClasses = numberOfClasses;
+ this.numberOfClassLoaders = numberOfClassLoaders;
+ this.usedHeapSize = usedHeapSize;
+ this.generationInfoAvailable = generationInfoAvailable;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/Info.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/Info.java
new file mode 100644
index 0000000..99e9493
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/Info.java
@@ -0,0 +1,47 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.thread;
+
+import lombok.Data;
+
+@Data
+public class Info {
+
+ private int objectId;
+
+ private String object;
+
+ private String name;
+
+ private long shallowSize;
+
+ private long retainedSize;
+
+ private String contextClassLoader;
+
+ private boolean hasStack;
+
+ private boolean daemon;
+
+ public Info(int objectId, String object, String name, long shallowSize, long retainedSize,
+ String contextClassLoader, boolean hasStack, boolean daemon) {
+ this.objectId = objectId;
+ this.object = object;
+ this.name = name;
+ this.shallowSize = shallowSize;
+ this.retainedSize = retainedSize;
+ this.contextClassLoader = contextClassLoader;
+ this.hasStack = hasStack;
+ this.daemon = daemon;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/LocalVariable.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/LocalVariable.java
new file mode 100644
index 0000000..d7e455a
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/LocalVariable.java
@@ -0,0 +1,22 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.thread;
+
+import org.eclipse.jifa.worker.vo.heapdump.HeapObject;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper=true)
+public class LocalVariable extends HeapObject {
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/StackFrame.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/StackFrame.java
new file mode 100644
index 0000000..386ee73
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/thread/StackFrame.java
@@ -0,0 +1,30 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.thread;
+
+import lombok.Data;
+
+@Data
+public class StackFrame {
+
+ private String stack;
+
+ private boolean hasLocal;
+
+ private boolean firstNonNativeFrame;
+
+ public StackFrame(String stack, boolean hasLocal) {
+ this.stack = stack;
+ this.hasLocal = hasLocal;
+ }
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Record.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Record.java
new file mode 100644
index 0000000..04df80d
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Record.java
@@ -0,0 +1,23 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.unreachable;
+
+import lombok.Data;
+
+@Data
+public class Record {
+ private int objectId;
+ private String className;
+ private int objects;
+ private long shallowSize;
+}
diff --git a/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Summary.java b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Summary.java
new file mode 100644
index 0000000..31254db
--- /dev/null
+++ b/backend/worker/src/main/java/org/eclipse/jifa/worker/vo/heapdump/unreachable/Summary.java
@@ -0,0 +1,25 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.vo.heapdump.unreachable;
+
+import lombok.Data;
+
+@Data
+public class Summary {
+
+ private int totalSize;
+
+ private int objects;
+
+ private long shallowSize;
+}
diff --git a/backend/worker/src/main/resources/log4j2-prod.xml b/backend/worker/src/main/resources/log4j2-prod.xml
new file mode 100644
index 0000000..9fa421c
--- /dev/null
+++ b/backend/worker/src/main/resources/log4j2-prod.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<Configuration status="WARN">
+ <Properties>
+ <Property name="baseDir">${sys:user.home}/logs/jifa</Property>
+ </Properties>
+ <Appenders>
+ <RollingFile name="STDOUT" append="false"
+ fileName="${baseDir}/stdout.log"
+ filePattern="${baseDir}/stdout-%d{yyyy-MM-dd}.log"
+ >
+ <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
+ <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%level] %m%n"/>
+ <Policies>
+ <TimeBasedTriggeringPolicy/>
+ </Policies>
+ </RollingFile>
+
+ <RollingFile name="STDERR" append="false"
+ fileName="${baseDir}/stderr.log"
+ filePattern="${baseDir}/stderr-%d{yyyy-MM-dd}.log"
+ >
+ <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
+ <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%level] %m%n"/>
+ <Policies>
+ <TimeBasedTriggeringPolicy/>
+ </Policies>
+ </RollingFile>
+ </Appenders>
+
+ <Loggers>
+ <Root level="info">
+ <AppenderRef ref="STDOUT"/>
+ <AppenderRef ref="STDERR"/>
+ </Root>
+
+ <Logger name="org.eclipse.jifa" level="info" additivity="false">
+ <AppenderRef ref="STDOUT"/>
+ <AppenderRef ref="STDERR"/>
+ </Logger>
+ </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/backend/worker/src/main/resources/log4j2-test.xml b/backend/worker/src/main/resources/log4j2-test.xml
new file mode 100644
index 0000000..b949fe7
--- /dev/null
+++ b/backend/worker/src/main/resources/log4j2-test.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="STDOUT" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] [%level] %m%n"/>
+ </Console>
+ </Appenders>
+
+ <Loggers>
+ <Logger name="org.eclipse.jifa" level="debug" additivity="false">
+ <AppenderRef ref="STDOUT"/>
+ </Logger>
+
+ <Root level="info">
+ <AppenderRef ref="STDOUT"/>
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/backend/worker/src/main/resources/vertx-config.json b/backend/worker/src/main/resources/vertx-config.json
new file mode 100644
index 0000000..b447e89
--- /dev/null
+++ b/backend/worker/src/main/resources/vertx-config.json
@@ -0,0 +1,5 @@
+{
+ "workerPoolSize": 32,
+ "maxWorkerExecuteTime": 15,
+ "maxWorkerExecuteTimeUnit": "MINUTES"
+}
\ No newline at end of file
diff --git a/backend/worker/src/main/resources/worker-config.json b/backend/worker/src/main/resources/worker-config.json
new file mode 100644
index 0000000..b1cd180
--- /dev/null
+++ b/backend/worker/src/main/resources/worker-config.json
@@ -0,0 +1,4 @@
+{
+ "server.port": 8102,
+ "api.prefix": "/jifa-api"
+}
\ No newline at end of file
diff --git a/backend/worker/src/test/java/org/eclipse/jifa/worker/route/Base.java b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/Base.java
new file mode 100644
index 0000000..c13af6a
--- /dev/null
+++ b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/Base.java
@@ -0,0 +1,30 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import io.vertx.core.Vertx;
+import io.vertx.ext.web.client.WebClient;
+import org.eclipse.jifa.worker.Constant;
+import org.eclipse.jifa.worker.Global;
+
+public class Base {
+
+ static WebClient CLIENT = WebClient.create(Vertx.vertx());
+
+ static String TEST_HEAP_DUMP_FILENAME;
+
+ public static String uri(String uri) {
+ return Global.stringConfig(Constant.ConfigKey.API_PREFIX) + uri;
+ }
+
+}
diff --git a/backend/worker/src/test/java/org/eclipse/jifa/worker/route/FileRouteSuite.java b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/FileRouteSuite.java
new file mode 100644
index 0000000..1f28e08
--- /dev/null
+++ b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/FileRouteSuite.java
@@ -0,0 +1,44 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import com.google.gson.reflect.TypeToken;
+import io.vertx.ext.unit.Async;
+import io.vertx.ext.unit.TestContext;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.vo.FileInfo;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.worker.Global;
+
+import java.lang.reflect.Type;
+
+import static org.eclipse.jifa.common.util.GsonHolder.GSON;
+
+public class FileRouteSuite extends Base {
+
+ public static void test(TestContext context) {
+ Async async = context.async();
+ CLIENT.get(Global.PORT, Global.HOST, uri("/files"))
+ .addQueryParam("type", FileType.HEAP_DUMP.name())
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .send(ar -> {
+ context.assertTrue(ar.succeeded());
+ Type type = new TypeToken<PageView<FileInfo>>() {
+ }.getType();
+ PageView<FileInfo> view = GSON.fromJson(ar.result().bodyAsString(), type);
+ context.assertTrue(view.getData().size() > 0);
+ async.complete();
+ });
+ }
+}
diff --git a/backend/worker/src/test/java/org/eclipse/jifa/worker/route/HeapDumpRouteSuite.java b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/HeapDumpRouteSuite.java
new file mode 100644
index 0000000..64a79dc
--- /dev/null
+++ b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/HeapDumpRouteSuite.java
@@ -0,0 +1,272 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import com.google.gson.reflect.TypeToken;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.ext.unit.Async;
+import io.vertx.ext.unit.TestContext;
+import io.vertx.ext.web.client.HttpRequest;
+import io.vertx.ext.web.client.HttpResponse;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.common.vo.PageView;
+import org.eclipse.jifa.common.vo.Progress;
+import org.eclipse.jifa.common.vo.Result;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.worker.vo.heapdump.classloader.Record;
+import org.eclipse.jifa.worker.vo.heapdump.inspector.ObjectView;
+import org.eclipse.jifa.worker.vo.heapdump.thread.Info;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Type;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.eclipse.jifa.common.Constant.HTTP_GET_OK_STATUS_CODE;
+import static org.eclipse.jifa.common.Constant.HTTP_POST_CREATED_STATUS_CODE;
+import static org.eclipse.jifa.common.util.GsonHolder.GSON;
+
+public class HeapDumpRouteSuite extends Base {
+
+ static TestContext context;
+ private static Logger LOGGER = LoggerFactory.getLogger(HeapDumpRouteSuite.class);
+
+ public static void test(TestContext c) throws Exception {
+ context = c;
+ Holder holder = new Holder();
+
+ testGet("/isFirstAnalysis",
+ (PostProcessor) resp -> {
+ Type type = new TypeToken<Result<Boolean>>() {
+ }.getType();
+ Result<Boolean> result = GSON.fromJson(resp.bodyAsString(), type);
+ context.assertTrue(result.getResult());
+
+ });
+
+ testPost("/analyze");
+
+ AtomicBoolean success = new AtomicBoolean();
+ while (!success.get()) {
+ testGet("/progressOfAnalysis",
+ (PostProcessor) resp -> {
+ Progress progress = GSON.fromJson(resp.bodyAsString(), Progress.class);
+ ProgressState state = progress.getState();
+ context.assertTrue(state == ProgressState.IN_PROGRESS || state == ProgressState.SUCCESS);
+ if (state == ProgressState.SUCCESS) {
+ success.set(true);
+ }
+ });
+ Thread.sleep(200);
+ }
+
+ // overview
+ testGet("/details");
+ testGet("/biggestObjects");
+
+ // class loader
+ testGet("/classLoaderExplorer/summary");
+ testGet("/classLoaderExplorer/classLoader",
+ req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"),
+ resp -> {
+ Type type = new TypeToken<PageView<Record>>() {
+ }.getType();
+ PageView<Record> result = GSON.fromJson(resp.bodyAsString(), type);
+ holder.id = result.getData().get(0).getObjectId();
+ });
+ testGet("/classLoaderExplorer/children",
+ (PreProcessor) req -> req.addQueryParam("classLoaderId", String.valueOf(holder.id))
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+
+ // class reference
+ testGet("/classReference/inbounds/class",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id)));
+ testGet("/classReference/outbounds/class",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id)));
+
+ // direct byte buffer
+ testGet("/directByteBuffer/summary");
+ testGet("/directByteBuffer/records",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+
+ // dominator tree
+ testGet("/dominatorTree/roots",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .addQueryParam("grouping", "NONE"));
+ testGet("/dominatorTree/children",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .addQueryParam("grouping", "NONE")
+ .addQueryParam("parentObjectId", String.valueOf(holder.id)));
+
+ // gc root
+ testGet("/GCRoots");
+ testGet("/GCRoots/classes",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .addQueryParam("rootTypeIndex", "1"));
+ testGet("/GCRoots/class/objects",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .addQueryParam("rootTypeIndex", "1")
+ .addQueryParam("classIndex", "1"));
+
+ // histogram
+ testGet("/histogram",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10")
+ .addQueryParam("groupingBy", "BY_CLASS"));
+
+ // inspector
+ testGet("/inspector/objectView",
+ req -> req.addQueryParam("objectId", String.valueOf(holder.id)),
+ resp -> {
+ ObjectView objectView = GSON.fromJson(resp.bodyAsString(), ObjectView.class);
+ holder.objectAddress = objectView.getObjectAddress();
+ });
+ testGet("/inspector/addressToId",
+ (PreProcessor) req -> req.addQueryParam("objectAddress", String.valueOf(holder.objectAddress)));
+ testGet("/inspector/value",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id)));
+ testGet("/inspector/fields",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id))
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+ testGet("/inspector/staticFields",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id))
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+
+ // leak report
+ testGet("/leak/report");
+
+ // object list
+ testGet("/outbounds",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id))
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+ testGet("/inbounds",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id))
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+
+ // object
+ testGet("/object",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id)));
+
+ // oql
+ testGet("/oql",
+ (PreProcessor) req -> req.addQueryParam("oql", "select * from java.lang.String")
+ .addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+
+ // path to gc roots
+ testGet("/pathToGCRoots",
+ (PreProcessor) req -> req.addQueryParam("origin", String.valueOf(holder.id))
+ .addQueryParam("skip", "0")
+ .addQueryParam("count", "10"));
+
+ // system property
+ testGet("/systemProperties");
+
+ // thread
+ testGet("/threadsSummary");
+ testGet("/threads",
+ req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"),
+ resp -> {
+ Type type = new TypeToken<PageView<Info>>() {
+ }.getType();
+ PageView<Info> result = GSON.fromJson(resp.bodyAsString(), type);
+ holder.id = result.getData().get(0).getObjectId();
+ }
+ );
+ testGet("/stackTrace",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id)));
+ testGet("/locals",
+ (PreProcessor) req -> req.addQueryParam("objectId", String.valueOf(holder.id))
+ .addQueryParam("depth", "1")
+ .addQueryParam("firstNonNativeFrame", "false"));
+
+
+ // unreachable objects
+ testGet("/unreachableObjects/summary");
+ testGet("/unreachableObjects/records",
+ (PreProcessor) req -> req.addQueryParam("page", "1")
+ .addQueryParam("pageSize", "10"));
+ }
+
+ static void testGet(String uri) {
+ testGet(uri, null, null);
+ }
+
+ static void testGet(String uri, PreProcessor processor) {
+ testGet(uri, processor, null);
+ }
+
+ static void testGet(String uri, PostProcessor postProcessor) {
+ testGet(uri, null, postProcessor);
+ }
+
+ static void testGet(String uri, PreProcessor processor, PostProcessor postProcessor) {
+ test(uri, HttpMethod.GET, processor, postProcessor);
+ }
+
+ static void testPost(String uri) {
+ test(uri, HttpMethod.POST, null, null);
+ }
+
+ static void test(String uri, HttpMethod method, PreProcessor processor, PostProcessor postProcessor) {
+ LOGGER.info("test {}", uri);
+ Async async = context.async();
+ HttpRequest<Buffer> request =
+ CLIENT.request(method, Global.PORT, Global.HOST, uri("/heap-dump/" + TEST_HEAP_DUMP_FILENAME + uri));
+ if (processor != null) {
+ processor.process(request);
+ }
+ request.send(
+ ar -> {
+ context.assertTrue(ar.succeeded());
+ context.assertEquals(ar.result().statusCode(),
+ method == HttpMethod.GET ? HTTP_GET_OK_STATUS_CODE : HTTP_POST_CREATED_STATUS_CODE,
+ ar.result().bodyAsString());
+
+ if (postProcessor != null) {
+ postProcessor.process(ar.result());
+ }
+ LOGGER.info("{}: {}", uri, ar.result().bodyAsString());
+ async.complete();
+ }
+ );
+ async.awaitSuccess();
+ }
+
+ interface PreProcessor {
+ void process(HttpRequest<Buffer> request);
+ }
+
+ interface PostProcessor {
+ void process(HttpResponse<Buffer> resp);
+ }
+
+ static class Holder {
+ int id;
+
+ long objectAddress;
+ }
+}
diff --git a/backend/worker/src/test/java/org/eclipse/jifa/worker/route/TestRoutes.java b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/TestRoutes.java
new file mode 100644
index 0000000..341a7bc
--- /dev/null
+++ b/backend/worker/src/test/java/org/eclipse/jifa/worker/route/TestRoutes.java
@@ -0,0 +1,71 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+package org.eclipse.jifa.worker.route;
+
+import com.google.common.io.Files;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import io.vertx.ext.unit.TestContext;
+import io.vertx.ext.unit.junit.VertxUnitRunner;
+import org.apache.commons.io.FileUtils;
+import org.eclipse.jifa.common.enums.FileType;
+import org.eclipse.jifa.common.enums.ProgressState;
+import org.eclipse.jifa.worker.Global;
+import org.eclipse.jifa.worker.Starter;
+import org.eclipse.jifa.worker.support.FileSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.lang.management.ManagementFactory;
+
+@RunWith(VertxUnitRunner.class)
+public class TestRoutes {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(TestRoutes.class);
+
+ @Before
+ public void setup(TestContext context) throws Exception {
+ // start worker
+ Starter.main(new String[]{});
+
+ // prepare heap dump file
+ HotSpotDiagnosticMXBean mxBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+ String name = "test_dump_" + System.currentTimeMillis() + ".hprof";
+ Base.TEST_HEAP_DUMP_FILENAME = name;
+ mxBean.dumpHeap(name, false);
+ FileSupport.initInfoFile(FileType.HEAP_DUMP, name, name);
+ Files.move(new File(name), new File(FileSupport.filePath(FileType.HEAP_DUMP, name)));
+ FileSupport.updateTransferState(FileType.HEAP_DUMP, name, ProgressState.SUCCESS);
+ }
+
+ @Test
+ public void testRoutes(TestContext context) throws Exception {
+ FileRouteSuite.test(context);
+ HeapDumpRouteSuite.test(context);
+ }
+
+ @After
+ public void tearDown(TestContext context) {
+ try {
+ System.out.println(context);
+ FileUtils.deleteDirectory(new File(Global.workspace()));
+ Global.VERTX.close(context.asyncAssertSuccess());
+ } catch (Throwable t) {
+ LOGGER.error("Error", t);
+ }
+ }
+}
diff --git a/backend/worker/src/test/resources/vertx-config.json b/backend/worker/src/test/resources/vertx-config.json
new file mode 100644
index 0000000..b447e89
--- /dev/null
+++ b/backend/worker/src/test/resources/vertx-config.json
@@ -0,0 +1,5 @@
+{
+ "workerPoolSize": 32,
+ "maxWorkerExecuteTime": 15,
+ "maxWorkerExecuteTimeUnit": "MINUTES"
+}
\ No newline at end of file
diff --git a/backend/worker/src/test/resources/worker-config.json b/backend/worker/src/test/resources/worker-config.json
new file mode 100644
index 0000000..340111c
--- /dev/null
+++ b/backend/worker/src/test/resources/worker-config.json
@@ -0,0 +1,5 @@
+{
+ "server.host": "localhost",
+ "api.prefix": "/jifa-api",
+ "workspace": ".test_jifa_workspace"
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..09e8d65
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,16 @@
+allprojects {
+ repositories {
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ }
+ jcenter()
+ mavenCentral()
+ }
+}
+
+subprojects {
+ apply plugin: 'idea'
+ version = '0.1'
+}
+
+defaultTasks 'build'
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..3b2cd3c
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,29 @@
+# jifa
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Run your tests
+```
+npm run test
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/frontend/babel.config.js b/frontend/babel.config.js
new file mode 100644
index 0000000..6f25b24
--- /dev/null
+++ b/frontend/babel.config.js
@@ -0,0 +1,17 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+module.exports = {
+ presets: [
+ '@vue/app'
+ ]
+}
diff --git a/frontend/build.gradle b/frontend/build.gradle
new file mode 100644
index 0000000..d3016d1
--- /dev/null
+++ b/frontend/build.gradle
@@ -0,0 +1,48 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+buildscript {
+ repositories {
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ }
+ }
+
+ dependencies {
+ classpath "com.moowork.gradle:gradle-node-plugin:1.3.1"
+ }
+}
+
+apply plugin: 'base'
+apply plugin: 'com.moowork.node'
+
+node {
+ version = '10.14.1'
+ npmVersion = '6.4.1'
+ download = true
+}
+
+npm_run_build {
+ inputs.files fileTree("public")
+ inputs.files fileTree("src")
+ inputs.file 'package.json'
+ inputs.file 'package-lock.json'
+ outputs.dir 'build'
+}
+
+task copy_build(type: Copy) {
+ dependsOn npm_run_build
+ from "build" as Object
+ into "${project.rootDir}/build/static" as Object
+}
+
+assemble.dependsOn copy_build
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
new file mode 100644
index 0000000..6381534
--- /dev/null
+++ b/frontend/package-lock.json
@@ -0,0 +1,12854 @@
+{
+ "name": "Jifa",
+ "version": "0.1.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.0.0.tgz",
+ "integrity": "sha1-BuKrGb21NThVWaq7W6WXKUgoAPg=",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.0.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/core/download/@babel/core-7.4.0.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.4.0.tgz",
+ "integrity": "sha1-JI/Wh0t9dVAQv+YfVXRh1PRG2ek=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/generator": "^7.4.0",
+ "@babel/helpers": "^7.4.0",
+ "@babel/parser": "^7.4.0",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.0",
+ "@babel/types": "^7.4.0",
+ "convert-source-map": "^1.1.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.11",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/generator": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.4.0.tgz",
+ "integrity": "sha1-wjDnlYmuenKf1GMbne1NwiBBgZY=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.0",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.11",
+ "source-map": "^0.5.0",
+ "trim-right": "^1.0.1"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.0.0.tgz",
+ "integrity": "sha1-Mj053QtQ4Qx8Bsp9djjmhk2MXDI=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.1.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
+ "integrity": "sha1-a2lijf5Ah3mODE7Zjj1Kay+9L18=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-call-delegate": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-call-delegate/download/@babel/helper-call-delegate-7.4.0.tgz",
+ "integrity": "sha1-8wjqvg1E9FEheFOu303qX2/jKU8=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.4.0",
+ "@babel/traverse": "^7.4.0",
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.4.0.tgz",
+ "integrity": "sha1-MP0JDgWdAhmVwXYqW3Z5j6C1HYI=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-member-expression-to-functions": "^7.0.0",
+ "@babel/helper-optimise-call-expression": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.4.0",
+ "@babel/helper-split-export-declaration": "^7.4.0"
+ }
+ },
+ "@babel/helper-define-map": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-define-map/download/@babel/helper-define-map-7.4.0.tgz",
+ "integrity": "sha1-y/2MGy8ScI4mLCb2AM0W7Wo7xsk=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/types": "^7.4.0",
+ "lodash": "^4.17.11"
+ }
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.1.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.1.0.tgz",
+ "integrity": "sha1-U3+hP28WdN90WwwA7I/k6ZaByPY=",
+ "dev": true,
+ "requires": {
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.1.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.1.0.tgz",
+ "integrity": "sha1-oM6wFoX3M1XUNgwSR/WCv6/I/1M=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/template": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.0.0.tgz",
+ "integrity": "sha1-g1ctQyDipGVyY3NBE8QoaLZOScM=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-hoist-variables/download/@babel/helper-hoist-variables-7.4.0.tgz",
+ "integrity": "sha1-JbYhOZriKYaTKXMKYgFbvrCm+9Y=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.0.0.tgz",
+ "integrity": "sha1-jNFLCg33/wDwCefXpDaUX0fHoW8=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.0.0.tgz",
+ "integrity": "sha1-lggbcRHkhtpNLNlxrRpP4hbMLj0=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.2.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.2.2.tgz",
+ "integrity": "sha1-qy+OjSMUCfg3DIg9IMM1GQKEuWM=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-simple-access": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.0.0",
+ "@babel/template": "^7.2.2",
+ "@babel/types": "^7.2.2",
+ "lodash": "^4.17.10"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.0.0.tgz",
+ "integrity": "sha1-opIMVwKwc8Fd5REGIAqoytIEl9U=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.0.0.tgz",
+ "integrity": "sha1-u7P77phmHFaQNCN8wDlnupm08lA=",
+ "dev": true
+ },
+ "@babel/helper-regex": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-regex/download/@babel/helper-regex-7.0.0.tgz",
+ "integrity": "sha1-LBcYkjtX+bvmRwX/5WQKxk2b2yc=",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.10"
+ }
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.1.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-remap-async-to-generator/download/@babel/helper-remap-async-to-generator-7.1.0.tgz",
+ "integrity": "sha1-Nh2AghtvONp1vT8HheziCojF/n8=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-wrap-function": "^7.1.0",
+ "@babel/template": "^7.1.0",
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.4.0.tgz",
+ "integrity": "sha1-T1attq7c1EnS2pOZwtzwVFRjtkw=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.0.0",
+ "@babel/helper-optimise-call-expression": "^7.0.0",
+ "@babel/traverse": "^7.4.0",
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.1.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.1.0.tgz",
+ "integrity": "sha1-Ze65VMjCRb6qToWdphiPOdceWFw=",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.4.0.tgz",
+ "integrity": "sha1-Vxv9UnAfSSkg1jt/c1Aw6aPhC1U=",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.2.0.tgz",
+ "integrity": "sha1-xOABJEV2nigVtVKW6tQ6lYVJ9vo=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/template": "^7.1.0",
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.2.0"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.4.2.tgz",
+ "integrity": "sha1-O9+kalUsp371oPhVG+XwhFrpib4=",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.0",
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/highlight/download/@babel/highlight-7.0.0.tgz",
+ "integrity": "sha1-9xDDjI1Fjm3ZogGvtjf8t4HOmeQ=",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.4.2.tgz",
+ "integrity": "sha1-tFIaQAy1qHHqs4kHh7S8EybTjZE=",
+ "dev": true
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.2.0.tgz",
+ "integrity": "sha1-somzBmadzkrSCwJSiJoVdoydQX4=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-remap-async-to-generator": "^7.1.0",
+ "@babel/plugin-syntax-async-generators": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.4.0.tgz",
+ "integrity": "sha1-1w22Gi8f153pJ+6pH2QRyWTghLg=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.4.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-proposal-decorators": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-decorators/download/@babel/plugin-proposal-decorators-7.4.0.tgz",
+ "integrity": "sha1-jhv9g++lSl9mIDOvzCuOcB9Ls6k=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.4.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-decorators": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.2.0.tgz",
+ "integrity": "sha1-Vo7MRGxhSK5rJn8CVREwiR4p8xc=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-json-strings": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.4.0.tgz",
+ "integrity": "sha1-5JYFdSBerfKhq04MeflQTVuCqX8=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.2.0.tgz",
+ "integrity": "sha1-E12B7baKCB5V5W7EhUHs6AZcOPU=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.4.0.tgz",
+ "integrity": "sha1-IC2R7pd9dg74P09BaygNVovoRiM=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.0.0",
+ "regexpu-core": "^4.5.4"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.2.0.tgz",
+ "integrity": "sha1-aeHw2zTG9aDPfiszI78VmnbIy38=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-decorators": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-decorators/download/@babel/plugin-syntax-decorators-7.2.0.tgz",
+ "integrity": "sha1-xQsblX3MaeSxEntl4cM+72FXDBs=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.2.0.tgz",
+ "integrity": "sha1-acFZ/69JmBIhYa2OvF5tH1XfhhI=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.2.0.tgz",
+ "integrity": "sha1-cr0T9v/h0lk4Ep0qGGsR/WKVFHA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.2.0.tgz",
+ "integrity": "sha1-C4WjtLx830zEuL8jYzW5B8oi58c=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.2.0.tgz",
+ "integrity": "sha1-O3o+czUQxX6CC5FCpleayLDfrS4=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.2.0.tgz",
+ "integrity": "sha1-qUAT1u2okI3+akd+f57ahWVuz1w=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.2.0.tgz",
+ "integrity": "sha1-mur75Nb/xlY7+Pg3IJFijwB3lVA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-async-to-generator/download/@babel/plugin-transform-async-to-generator-7.4.0.tgz",
+ "integrity": "sha1-I0/j5Fjc6VhlwNFS0lYRmyN4NLA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-remap-async-to-generator": "^7.1.0"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.2.0.tgz",
+ "integrity": "sha1-XTzBHo1d3XUqpkyRSNDbbLef0ZA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.4.0.tgz",
+ "integrity": "sha1-Fk3zu0Hj3rlUxMoy/6n8qlbTC8s=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "lodash": "^4.17.11"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.4.0.tgz",
+ "integrity": "sha1-40KNPIo9AfM7EMUpuZi6FwcEPU0=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-define-map": "^7.4.0",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-optimise-call-expression": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.4.0",
+ "@babel/helper-split-export-declaration": "^7.4.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.2.0.tgz",
+ "integrity": "sha1-g6ffamWIZbHI9kHVEMbzryICFto=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.4.0.tgz",
+ "integrity": "sha1-rLubJBjSkBB9szP01s2Kpq6gA0M=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-dotall-regex/download/@babel/plugin-transform-dotall-regex-7.2.0.tgz",
+ "integrity": "sha1-8Kq7k9EgqKxh6SXqC6RAgS2+Dkk=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.0.0",
+ "regexpu-core": "^4.1.3"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-duplicate-keys/download/@babel/plugin-transform-duplicate-keys-7.2.0.tgz",
+ "integrity": "sha1-2VLEkw8xKk2//xjwspFOYMNVMLM=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.2.0.tgz",
+ "integrity": "sha1-pjhoKJ5bQAf3BU1GSRr1FDV2YAg=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.4.0.tgz",
+ "integrity": "sha1-VsjDZnf11KFrgLEve3aN4GSq618=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.2.0.tgz",
+ "integrity": "sha1-95MDYoKf+ZoxdMOfCvzAJO9Zcxo=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.2.0.tgz",
+ "integrity": "sha1-aQNT6B+SZ9rU/Yz9d+r6hqulPqE=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.2.0.tgz",
+ "integrity": "sha1-gqm85FuVRB9heiQBHcidEtp/TuY=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.4.0.tgz",
+ "integrity": "sha1-O47GFxTTt10gxcz6FX8sLgh/1Mo=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-simple-access": "^7.1.0"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-modules-systemjs/download/@babel/plugin-transform-modules-systemjs-7.4.0.tgz",
+ "integrity": "sha1-wkleVVKBNXl7yBb11Q+FFpjFhqE=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.4.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.2.0.tgz",
+ "integrity": "sha1-dnjOdRafCHe46yI1U4wHQmjdAa4=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-named-capturing-groups-regex/download/@babel/plugin-transform-named-capturing-groups-regex-7.4.2.tgz",
+ "integrity": "sha1-gAORE21svMgHKNvbo8HG5G+GwS4=",
+ "dev": true,
+ "requires": {
+ "regexp-tree": "^0.1.0"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-new-target/download/@babel/plugin-transform-new-target-7.4.0.tgz",
+ "integrity": "sha1-Z2WKHZRO21PI1PowBEc6DdeDgVA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.2.0.tgz",
+ "integrity": "sha1-s11MEPVrq11lAEfa0PHY6IFLZZg=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.1.0"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.4.0.tgz",
+ "integrity": "sha1-oTCUJvrE7s0qlDmkyMNRJKEaSKk=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-call-delegate": "^7.4.0",
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.4.0.tgz",
+ "integrity": "sha1-B4DifuRYzD/brRgpTXA+lyrh9tE=",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "^0.13.4"
+ }
+ },
+ "@babel/plugin-transform-runtime": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.4.0.tgz",
+ "integrity": "sha1-tNjJJe2VdHG8V+C52lNAjrse1Fc=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "resolve": "^1.8.1",
+ "semver": "^5.5.1"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.2.0.tgz",
+ "integrity": "sha1-YzOu4vjW7n4oYVRXKYk0o7RhmPA=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.2.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.2.2.tgz",
+ "integrity": "sha1-MQOpq+IvdCttQG7NPNSbd0kZtAY=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.2.0.tgz",
+ "integrity": "sha1-oeRUtZlVYKnB4NU338FQYf0mh+E=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.2.0.tgz",
+ "integrity": "sha1-2H7QG46qx6kkc/YIyXwIneK6Hls=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-typeof-symbol/download/@babel/plugin-transform-typeof-symbol-7.2.0.tgz",
+ "integrity": "sha1-EX0rzsL79ktLWdH5gZiUaC0p8rI=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.2.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.2.0.tgz",
+ "integrity": "sha1-TrjbFvly+Ku1BiwWG4sRVUat4Is=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.0.0",
+ "regexpu-core": "^4.1.3"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.4.2.tgz",
+ "integrity": "sha1-L1uh3i2u+p3MplOEj5bHzi5AZnY=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
+ "@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.0",
+ "@babel/plugin-syntax-async-generators": "^7.2.0",
+ "@babel/plugin-syntax-json-strings": "^7.2.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-transform-arrow-functions": "^7.2.0",
+ "@babel/plugin-transform-async-to-generator": "^7.4.0",
+ "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
+ "@babel/plugin-transform-block-scoping": "^7.4.0",
+ "@babel/plugin-transform-classes": "^7.4.0",
+ "@babel/plugin-transform-computed-properties": "^7.2.0",
+ "@babel/plugin-transform-destructuring": "^7.4.0",
+ "@babel/plugin-transform-dotall-regex": "^7.2.0",
+ "@babel/plugin-transform-duplicate-keys": "^7.2.0",
+ "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
+ "@babel/plugin-transform-for-of": "^7.4.0",
+ "@babel/plugin-transform-function-name": "^7.2.0",
+ "@babel/plugin-transform-literals": "^7.2.0",
+ "@babel/plugin-transform-modules-amd": "^7.2.0",
+ "@babel/plugin-transform-modules-commonjs": "^7.4.0",
+ "@babel/plugin-transform-modules-systemjs": "^7.4.0",
+ "@babel/plugin-transform-modules-umd": "^7.2.0",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.2",
+ "@babel/plugin-transform-new-target": "^7.4.0",
+ "@babel/plugin-transform-object-super": "^7.2.0",
+ "@babel/plugin-transform-parameters": "^7.4.0",
+ "@babel/plugin-transform-regenerator": "^7.4.0",
+ "@babel/plugin-transform-shorthand-properties": "^7.2.0",
+ "@babel/plugin-transform-spread": "^7.2.0",
+ "@babel/plugin-transform-sticky-regex": "^7.2.0",
+ "@babel/plugin-transform-template-literals": "^7.2.0",
+ "@babel/plugin-transform-typeof-symbol": "^7.2.0",
+ "@babel/plugin-transform-unicode-regex": "^7.2.0",
+ "@babel/types": "^7.4.0",
+ "browserslist": "^4.4.2",
+ "core-js-compat": "^3.0.0",
+ "invariant": "^2.2.2",
+ "js-levenshtein": "^1.1.3",
+ "semver": "^5.3.0"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.4.2.tgz",
+ "integrity": "sha1-9atolzIPFt7NhV7tcLcFkIoxP+g=",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
+ "@babel/runtime-corejs2": {
+ "version": "7.4.2",
+ "resolved": "http://registry.npm.taobao.org/@babel/runtime-corejs2/download/@babel/runtime-corejs2-7.4.2.tgz",
+ "integrity": "sha1-oM7CxBcX+kFenCBPMrYD2IsXlsI=",
+ "dev": true,
+ "requires": {
+ "core-js": "^2.6.5",
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
+ "@babel/template": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/template/download/@babel/template-7.4.0.tgz",
+ "integrity": "sha1-EkdOnAd7rlhcXYNalcCwt5DCXIs=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.4.0",
+ "@babel/types": "^7.4.0"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.4.0.tgz",
+ "integrity": "sha1-FABpZ90dKzSUzdZQxobbna8N2to=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/generator": "^7.4.0",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.4.0",
+ "@babel/parser": "^7.4.0",
+ "@babel/types": "^7.4.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.11"
+ }
+ },
+ "@babel/types": {
+ "version": "7.4.0",
+ "resolved": "http://registry.npm.taobao.org/@babel/types/download/@babel/types-7.4.0.tgz",
+ "integrity": "sha1-Zwck930kzObMfYz2RZnVEdFkiUw=",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.11",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@fortawesome/fontawesome-free": {
+ "version": "5.12.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.12.1.tgz",
+ "integrity": "sha512-ZtjIIFplxncqxvogq148C3hBLQE+W3iJ8E4UvJ09zIJUgzwLcROsWwFDErVSXY2Plzao5J9KUYNHKHMEUYDMKw=="
+ },
+ "@intervolga/optimize-cssnano-plugin": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz",
+ "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==",
+ "dev": true,
+ "requires": {
+ "cssnano": "^4.0.0",
+ "cssnano-preset-default": "^4.0.0",
+ "postcss": "^7.0.0"
+ }
+ },
+ "@mrmlnc/readdir-enhanced": {
+ "version": "2.2.1",
+ "resolved": "http://registry.npm.taobao.org/@mrmlnc/readdir-enhanced/download/@mrmlnc/readdir-enhanced-2.2.1.tgz",
+ "integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=",
+ "dev": true,
+ "requires": {
+ "call-me-maybe": "^1.0.1",
+ "glob-to-regexp": "^0.3.0"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-1.1.3.tgz",
+ "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=",
+ "dev": true
+ },
+ "@nuxt/opencollective": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.2.2.tgz",
+ "integrity": "sha512-ie50SpS47L+0gLsW4yP23zI/PtjsDRglyozX2G09jeiUazC1AJlGPZo0JUs9iuCDUoIgsDEf66y7/bSfig0BpA==",
+ "requires": {
+ "chalk": "^2.4.1",
+ "consola": "^2.3.0",
+ "node-fetch": "^2.3.0"
+ }
+ },
+ "@soda/friendly-errors-webpack-plugin": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
+ "integrity": "sha512-cWKrGaFX+rfbMrAxVv56DzhPNqOJPZuNIS2HGMELtgGzb+vsMzyig9mml5gZ/hr2BGtSLV+dP2LUEuAL8aG2mQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "error-stack-parser": "^2.0.0",
+ "string-width": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "@types/events": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/@types/events/download/@types/events-3.0.0.tgz",
+ "integrity": "sha1-KGLz9Yqaf3w+eNefEw3U1xwlwqc=",
+ "dev": true
+ },
+ "@types/glob": {
+ "version": "7.1.1",
+ "resolved": "http://registry.npm.taobao.org/@types/glob/download/@types/glob-7.1.1.tgz",
+ "integrity": "sha1-qlmhxuP7xCHgfM0xqUTDDrpSFXU=",
+ "dev": true,
+ "requires": {
+ "@types/events": "*",
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "http://registry.npm.taobao.org/@types/minimatch/download/@types/minimatch-3.0.3.tgz",
+ "integrity": "sha1-PcoOPzOyAPx9ETnAzZbBJoyt/Z0=",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "11.11.5",
+ "resolved": "http://registry.npm.taobao.org/@types/node/download/@types/node-11.11.5.tgz",
+ "integrity": "sha1-DFfhLrRNROW2c1WTklKGVT7nzr8=",
+ "dev": true
+ },
+ "@types/q": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
+ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
+ "dev": true
+ },
+ "@vue/babel-helper-vue-jsx-merge-props": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-helper-vue-jsx-merge-props/download/@vue/babel-helper-vue-jsx-merge-props-1.0.0-beta.3.tgz",
+ "integrity": "sha1-5MLnEls+DSqdST5FeFCyq7D9PK0=",
+ "dev": true
+ },
+ "@vue/babel-plugin-transform-vue-jsx": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-plugin-transform-vue-jsx/download/@vue/babel-plugin-transform-vue-jsx-1.0.0-beta.3.tgz",
+ "integrity": "sha1-oaROgB2O1hXknxRe8bPqyiwW4uY=",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0-beta.3",
+ "html-tags": "^2.0.0",
+ "lodash.kebabcase": "^4.1.1",
+ "svg-tags": "^1.0.0"
+ }
+ },
+ "@vue/babel-preset-app": {
+ "version": "3.5.1",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-preset-app/download/@vue/babel-preset-app-3.5.1.tgz",
+ "integrity": "sha1-Ez/oMsy5pVe6lG+mYDXb5bnGHlk=",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-proposal-class-properties": "^7.0.0",
+ "@babel/plugin-proposal-decorators": "^7.1.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.0.0",
+ "@babel/plugin-transform-runtime": "^7.0.0",
+ "@babel/preset-env": "^7.0.0",
+ "@babel/runtime": "^7.0.0",
+ "@babel/runtime-corejs2": "^7.2.0",
+ "@vue/babel-preset-jsx": "^1.0.0-beta.2",
+ "babel-plugin-dynamic-import-node": "^2.2.0",
+ "core-js": "^2.6.5"
+ }
+ },
+ "@vue/babel-preset-jsx": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-preset-jsx/download/@vue/babel-preset-jsx-1.0.0-beta.3.tgz",
+ "integrity": "sha1-FcWEvWLAKGqA8BlnSa44zeXNcDs=",
+ "dev": true,
+ "requires": {
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0-beta.3",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0-beta.3",
+ "@vue/babel-sugar-functional-vue": "^1.0.0-beta.3",
+ "@vue/babel-sugar-inject-h": "^1.0.0-beta.3",
+ "@vue/babel-sugar-v-model": "^1.0.0-beta.3",
+ "@vue/babel-sugar-v-on": "^1.0.0-beta.3"
+ }
+ },
+ "@vue/babel-sugar-functional-vue": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-sugar-functional-vue/download/@vue/babel-sugar-functional-vue-1.0.0-beta.3.tgz",
+ "integrity": "sha1-QahVeGlx2su+gESFju/pjeCJvxI=",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0"
+ }
+ },
+ "@vue/babel-sugar-inject-h": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-sugar-inject-h/download/@vue/babel-sugar-inject-h-1.0.0-beta.3.tgz",
+ "integrity": "sha1-vh0At0oaif7TWpsUFac4w28SWWY=",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0"
+ }
+ },
+ "@vue/babel-sugar-v-model": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-sugar-v-model/download/@vue/babel-sugar-v-model-1.0.0-beta.3.tgz",
+ "integrity": "sha1-6pNbDgi/WMEloTSbgZFWBZWQmTw=",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0-beta.3",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0-beta.3",
+ "camelcase": "^5.0.0",
+ "html-tags": "^2.0.0",
+ "svg-tags": "^1.0.0"
+ }
+ },
+ "@vue/babel-sugar-v-on": {
+ "version": "1.0.0-beta.3",
+ "resolved": "http://registry.npm.taobao.org/@vue/babel-sugar-v-on/download/@vue/babel-sugar-v-on-1.0.0-beta.3.tgz",
+ "integrity": "sha1-L1/ttDiD9gP+dgEPJTuFx0ZYVf4=",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.0.0-beta.3",
+ "camelcase": "^5.0.0"
+ }
+ },
+ "@vue/cli-overlay": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-3.6.0.tgz",
+ "integrity": "sha512-U9zcnnISJCA+dp7lLr1gTYfVqGfQ+y0jJ8LCZsZPxHpHr1QQDfMv9zqGOXQlv2+UVshvLi8ZWvD5AZSfHZ5h7w==",
+ "dev": true
+ },
+ "@vue/cli-plugin-babel": {
+ "version": "3.5.1",
+ "resolved": "http://registry.npm.taobao.org/@vue/cli-plugin-babel/download/@vue/cli-plugin-babel-3.5.1.tgz",
+ "integrity": "sha1-q4cp/1O7UIYTuZjN0uJaeN79MMg=",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.0.0",
+ "@vue/babel-preset-app": "^3.5.1",
+ "@vue/cli-shared-utils": "^3.5.1",
+ "babel-loader": "^8.0.5",
+ "webpack": ">=4 < 4.29"
+ }
+ },
+ "@vue/cli-plugin-eslint": {
+ "version": "3.5.1",
+ "resolved": "http://registry.npm.taobao.org/@vue/cli-plugin-eslint/download/@vue/cli-plugin-eslint-3.5.1.tgz",
+ "integrity": "sha1-ILRom+NdayFGy94utvnS8wM6DoE=",
+ "dev": true,
+ "requires": {
+ "@vue/cli-shared-utils": "^3.5.1",
+ "babel-eslint": "^10.0.1",
+ "eslint": "^4.19.1",
+ "eslint-loader": "^2.1.2",
+ "eslint-plugin-vue": "^4.7.1",
+ "globby": "^9.0.0",
+ "webpack": ">=4 < 4.29"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "optional": true
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz",
+ "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "eslint": {
+ "version": "4.19.1",
+ "resolved": "http://registry.npm.taobao.org/eslint/download/eslint-4.19.1.tgz",
+ "integrity": "sha1-MtHWU+HZBAiFS/spbwdux+GGowA=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ajv": "^5.3.0",
+ "babel-code-frame": "^6.22.0",
+ "chalk": "^2.1.0",
+ "concat-stream": "^1.6.0",
+ "cross-spawn": "^5.1.0",
+ "debug": "^3.1.0",
+ "doctrine": "^2.1.0",
+ "eslint-scope": "^3.7.1",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^3.5.4",
+ "esquery": "^1.0.0",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^2.0.0",
+ "functional-red-black-tree": "^1.0.1",
+ "glob": "^7.1.2",
+ "globals": "^11.0.1",
+ "ignore": "^3.3.3",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^3.0.6",
+ "is-resolvable": "^1.0.0",
+ "js-yaml": "^3.9.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.4",
+ "minimatch": "^3.0.2",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.2",
+ "path-is-inside": "^1.0.2",
+ "pluralize": "^7.0.0",
+ "progress": "^2.0.0",
+ "regexpp": "^1.0.1",
+ "require-uncached": "^1.0.3",
+ "semver": "^5.3.0",
+ "strip-ansi": "^4.0.0",
+ "strip-json-comments": "~2.0.1",
+ "table": "4.0.2",
+ "text-table": "~0.2.0"
+ }
+ },
+ "eslint-plugin-vue": {
+ "version": "4.7.1",
+ "resolved": "http://registry.npm.taobao.org/eslint-plugin-vue/download/eslint-plugin-vue-4.7.1.tgz",
+ "integrity": "sha1-yCm5/GJYLBiXtaC5Sv1E7MpRHmM=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "vue-eslint-parser": "^2.0.3"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.3",
+ "resolved": "http://registry.npm.taobao.org/eslint-scope/download/eslint-scope-3.7.3.tgz",
+ "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true,
+ "optional": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true,
+ "optional": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-4.1.5.tgz",
+ "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "@vue/cli-service": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-3.6.0.tgz",
+ "integrity": "sha512-MJeSjIf/IposSjJ93kRs5R8pfxqO7j2eXcIes2bwt3J9Ql8aoO5XAUi7IZphaxZHANIIbYJno+OUVtf90yMaqg==",
+ "dev": true,
+ "requires": {
+ "@intervolga/optimize-cssnano-plugin": "^1.0.5",
+ "@soda/friendly-errors-webpack-plugin": "^1.7.1",
+ "@vue/cli-overlay": "^3.6.0",
+ "@vue/cli-shared-utils": "^3.6.0",
+ "@vue/component-compiler-utils": "^2.6.0",
+ "@vue/preload-webpack-plugin": "^1.1.0",
+ "@vue/web-component-wrapper": "^1.2.0",
+ "acorn": "^6.1.1",
+ "acorn-walk": "^6.1.1",
+ "address": "^1.0.3",
+ "autoprefixer": "^9.5.1",
+ "browserslist": "^4.5.4",
+ "cache-loader": "^2.0.1",
+ "case-sensitive-paths-webpack-plugin": "^2.2.0",
+ "chalk": "^2.4.2",
+ "clipboardy": "^2.0.0",
+ "cliui": "^5.0.0",
+ "copy-webpack-plugin": "^4.6.0",
+ "css-loader": "^1.0.1",
+ "cssnano": "^4.1.10",
+ "current-script-polyfill": "^1.0.0",
+ "debug": "^4.1.1",
+ "dotenv": "^7.0.0",
+ "dotenv-expand": "^5.1.0",
+ "escape-string-regexp": "^1.0.5",
+ "file-loader": "^3.0.1",
+ "fs-extra": "^7.0.1",
+ "globby": "^9.2.0",
+ "hash-sum": "^1.0.2",
+ "html-webpack-plugin": "^3.2.0",
+ "launch-editor-middleware": "^2.2.1",
+ "lodash.defaultsdeep": "^4.6.0",
+ "lodash.mapvalues": "^4.6.0",
+ "lodash.transform": "^4.6.0",
+ "mini-css-extract-plugin": "^0.6.0",
+ "minimist": "^1.2.0",
+ "ora": "^3.4.0",
+ "portfinder": "^1.0.20",
+ "postcss-loader": "^3.0.0",
+ "read-pkg": "^5.0.0",
+ "semver": "^6.0.0",
+ "slash": "^2.0.0",
+ "source-map-url": "^0.4.0",
+ "ssri": "^6.0.1",
+ "string.prototype.padend": "^3.0.0",
+ "terser-webpack-plugin": "^1.2.3",
+ "thread-loader": "^2.1.2",
+ "url-loader": "^1.1.2",
+ "vue-loader": "^15.7.0",
+ "webpack": ">=4 < 4.29",
+ "webpack-bundle-analyzer": "^3.3.0",
+ "webpack-chain": "^4.11.0",
+ "webpack-dev-server": "^3.3.1",
+ "webpack-merge": "^4.2.1",
+ "yorkie": "^2.0.0"
+ },
+ "dependencies": {
+ "@vue/cli-shared-utils": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-3.6.0.tgz",
+ "integrity": "sha512-C8nTiJ7o+dncNLyOIOZF8P4bMJdOVXhWOuwyZKqn8k3CcsQVzuLyCKUHHezWc+sI+PJi4wIg2ZffCiueeIXZ+w==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "execa": "^1.0.0",
+ "joi": "^14.3.0",
+ "launch-editor": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "node-ipc": "^9.1.1",
+ "opn": "^5.3.0",
+ "ora": "^3.4.0",
+ "request": "^2.87.0",
+ "request-promise-native": "^1.0.7",
+ "semver": "^6.0.0",
+ "string.prototype.padstart": "^3.0.0"
+ }
+ },
+ "acorn": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+ "dev": true
+ },
+ "browserslist": {
+ "version": "4.5.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz",
+ "integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000960",
+ "electron-to-chromium": "^1.3.124",
+ "node-releases": "^1.1.14"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000962",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000962.tgz",
+ "integrity": "sha512-WXYsW38HK+6eaj5IZR16Rn91TGhU3OhbwjKZvJ4HN/XBIABLKfbij9Mnd3pM0VEwZSlltWjoWg3I8FQ0DGgNOA==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.124",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz",
+ "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==",
+ "dev": true
+ },
+ "globby": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz",
+ "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^1.0.2",
+ "dir-glob": "^2.2.2",
+ "fast-glob": "^2.2.6",
+ "glob": "^7.1.3",
+ "ignore": "^4.0.3",
+ "pify": "^4.0.1",
+ "slash": "^2.0.0"
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.15.tgz",
+ "integrity": "sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+ "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "dev": true
+ }
+ }
+ },
+ "ora": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
+ "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-spinners": "^2.0.0",
+ "log-symbols": "^2.2.0",
+ "strip-ansi": "^5.2.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "semver": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz",
+ "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==",
+ "dev": true
+ }
+ }
+ },
+ "@vue/cli-shared-utils": {
+ "version": "3.5.1",
+ "resolved": "http://registry.npm.taobao.org/@vue/cli-shared-utils/download/@vue/cli-shared-utils-3.5.1.tgz",
+ "integrity": "sha1-cdZvBvxhm6KN8nm9fTe6G6KckGY=",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "execa": "^1.0.0",
+ "joi": "^14.3.0",
+ "launch-editor": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "node-ipc": "^9.1.1",
+ "opn": "^5.3.0",
+ "ora": "^3.1.0",
+ "request": "^2.87.0",
+ "request-promise-native": "^1.0.7",
+ "semver": "^5.5.0",
+ "string.prototype.padstart": "^3.0.0"
+ }
+ },
+ "@vue/component-compiler-utils": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz",
+ "integrity": "sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==",
+ "dev": true,
+ "requires": {
+ "consolidate": "^0.15.1",
+ "hash-sum": "^1.0.2",
+ "lru-cache": "^4.1.2",
+ "merge-source-map": "^1.1.0",
+ "postcss": "^7.0.14",
+ "postcss-selector-parser": "^5.0.0",
+ "prettier": "1.16.3",
+ "source-map": "~0.6.1",
+ "vue-template-es2015-compiler": "^1.9.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "@vue/preload-webpack-plugin": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.0.tgz",
+ "integrity": "sha512-rcn2KhSHESBFMPj5vc5X2pI9bcBNQQixvJXhD5gZ4rN2iym/uH2qfDSQfUS5+qwiz0a85TCkeUs6w6jxFDudbw==",
+ "dev": true
+ },
+ "@vue/web-component-wrapper": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.2.0.tgz",
+ "integrity": "sha512-Xn/+vdm9CjuC9p3Ae+lTClNutrVhsXpzxvoTXXtoys6kVRX9FkueSUAqSWAyZntmVLlR4DosBV4pH8y5Z/HbUw==",
+ "dev": true
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/ast/download/@webassemblyjs/ast-1.7.11.tgz",
+ "integrity": "sha1-uYhYLK+7Kwlei1VlJvMMkNBXys4=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/floating-point-hex-parser/download/@webassemblyjs/floating-point-hex-parser-1.7.11.tgz",
+ "integrity": "sha1-pp8K9lAuuaPARVVbGmEp09Py4xM=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-api-error/download/@webassemblyjs/helper-api-error-1.7.11.tgz",
+ "integrity": "sha1-x7a7gQX4QDlRGis5zklPGTgYoyo=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-buffer/download/@webassemblyjs/helper-buffer-1.7.11.tgz",
+ "integrity": "sha1-MSLUjcxslFbtmC3r4WyPNxAd85s=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-code-frame/download/@webassemblyjs/helper-code-frame-1.7.11.tgz",
+ "integrity": "sha1-z48QbnRmYqDaKb3vY1/NPRJINks=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.7.11"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-fsm/download/@webassemblyjs/helper-fsm-1.7.11.tgz",
+ "integrity": "sha1-3ziIKmJAgNA/dQP5Pj8XrFrAEYE=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-module-context/download/@webassemblyjs/helper-module-context-1.7.11.tgz",
+ "integrity": "sha1-2HTXIuUeYqwgJHaTXWScgC+g4gk=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-wasm-bytecode/download/@webassemblyjs/helper-wasm-bytecode-1.7.11.tgz",
+ "integrity": "sha1-3ZoegX8cLrEFtM8QEwk8ufPJywY=",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/helper-wasm-section/download/@webassemblyjs/helper-wasm-section-1.7.11.tgz",
+ "integrity": "sha1-nJrEHs+fvP/8lvbSZ14t4zgR5oo=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/ieee754/download/@webassemblyjs/ieee754-1.7.11.tgz",
+ "integrity": "sha1-yVg562N1ejGICq7HtlEtQZGsZAs=",
+ "dev": true,
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/leb128/download/@webassemblyjs/leb128-1.7.11.tgz",
+ "integrity": "sha1-1yZ6HunEWU/T9+NymIGOxlaH22M=",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/utf8/download/@webassemblyjs/utf8-1.7.11.tgz",
+ "integrity": "sha1-Btchjqn9yUpnk6qSIIFg2z0m7oI=",
+ "dev": true
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wasm-edit/download/@webassemblyjs/wasm-edit-1.7.11.tgz",
+ "integrity": "sha1-jHTKR01PlR0B266b1wgU7iKoIAU=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/helper-wasm-section": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-opt": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "@webassemblyjs/wast-printer": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wasm-gen/download/@webassemblyjs/wasm-gen-1.7.11.tgz",
+ "integrity": "sha1-m7upQvIjdWhqb7dZr816ycRdoag=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wasm-opt/download/@webassemblyjs/wasm-opt-1.7.11.tgz",
+ "integrity": "sha1-szHo5874+OLwB9QsOjagWAp9bKc=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-buffer": "1.7.11",
+ "@webassemblyjs/wasm-gen": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wasm-parser/download/@webassemblyjs/wasm-parser-1.7.11.tgz",
+ "integrity": "sha1-bj0g+mo1GfawhO+Tka1YIR77Cho=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-wasm-bytecode": "1.7.11",
+ "@webassemblyjs/ieee754": "1.7.11",
+ "@webassemblyjs/leb128": "1.7.11",
+ "@webassemblyjs/utf8": "1.7.11"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wast-parser/download/@webassemblyjs/wast-parser-1.7.11.tgz",
+ "integrity": "sha1-Jb0RdWLKjAAnIP+BFu+QctnKhpw=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/floating-point-hex-parser": "1.7.11",
+ "@webassemblyjs/helper-api-error": "1.7.11",
+ "@webassemblyjs/helper-code-frame": "1.7.11",
+ "@webassemblyjs/helper-fsm": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.7.11",
+ "resolved": "http://registry.npm.taobao.org/@webassemblyjs/wast-printer/download/@webassemblyjs/wast-printer-1.7.11.tgz",
+ "integrity": "sha1-xCRbbeJCy1CizJUBdP2/ZceNeBM=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/wast-parser": "1.7.11",
+ "@xtuc/long": "4.2.1"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/@xtuc/ieee754/download/@xtuc/ieee754-1.2.0.tgz",
+ "integrity": "sha1-7vAUoxRa5Hehy8AM0eVSM23Ot5A=",
+ "dev": true
+ },
+ "@xtuc/long": {
+ "version": "4.2.1",
+ "resolved": "http://registry.npm.taobao.org/@xtuc/long/download/@xtuc/long-4.2.1.tgz",
+ "integrity": "sha1-XIXWYvdvodNFdXZsXc1mFavNMNg=",
+ "dev": true
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "accepts": {
+ "version": "1.3.5",
+ "resolved": "http://registry.npm.taobao.org/accepts/download/accepts-1.3.5.tgz",
+ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.18",
+ "negotiator": "0.6.1"
+ }
+ },
+ "acorn": {
+ "version": "5.7.3",
+ "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-5.7.3.tgz",
+ "integrity": "sha1-Z6ojG/iBKXS4UjWpZ3Hra9B+onk=",
+ "dev": true
+ },
+ "acorn-dynamic-import": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/acorn-dynamic-import/download/acorn-dynamic-import-3.0.0.tgz",
+ "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=",
+ "dev": true,
+ "requires": {
+ "acorn": "^5.0.0"
+ }
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "acorn": "^3.0.4"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "http://registry.npm.taobao.org/acorn/download/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
+ "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
+ "dev": true
+ },
+ "address": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
+ "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.10.0",
+ "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-6.10.0.tgz",
+ "integrity": "sha1-kNDVRDnaWHzX6EO/twRfUL0ivfE=",
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/ajv-errors/download/ajv-errors-1.0.1.tgz",
+ "integrity": "sha1-81mGrOuRr63sQQL72FAUlQzvpk0=",
+ "dev": true
+ },
+ "ajv-keywords": {
+ "version": "3.4.0",
+ "resolved": "http://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.4.0.tgz",
+ "integrity": "sha1-S4Mee1MUFafMUYzUBOc/YZPGNJ0=",
+ "dev": true
+ },
+ "alphanum-sort": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/alphanum-sort/download/alphanum-sort-1.0.2.tgz",
+ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+ "dev": true
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
+ },
+ "ansi-colors": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.2.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s=",
+ "dev": true
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "http://registry.npm.taobao.org/ansi-html/download/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz",
+ "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz",
+ "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=",
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz",
+ "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ },
+ "dependencies": {
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ }
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/aproba/download/aproba-1.2.0.tgz",
+ "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo="
+ },
+ "arch": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz",
+ "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==",
+ "dev": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz",
+ "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "http://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-filter": {
+ "version": "0.0.1",
+ "resolved": "http://registry.npm.taobao.org/array-filter/download/array-filter-0.0.1.tgz",
+ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=",
+ "dev": true
+ },
+ "array-find-index": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/array-flatten/download/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
+ "array-map": {
+ "version": "0.0.0",
+ "resolved": "http://registry.npm.taobao.org/array-map/download/array-map-0.0.0.tgz",
+ "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=",
+ "dev": true
+ },
+ "array-reduce": {
+ "version": "0.0.0",
+ "resolved": "http://registry.npm.taobao.org/array-reduce/download/array-reduce-0.0.0.tgz",
+ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "http://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz",
+ "integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "http://registry.npm.taobao.org/asn1.js/download/asn1.js-4.10.1.tgz",
+ "integrity": "sha1-ucK/WAXx5kqt7tbfOiv6+1pz9aA=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "http://registry.npm.taobao.org/assert/download/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "dev": true,
+ "requires": {
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/inherits/download/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "http://registry.npm.taobao.org/util/download/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/astral-regex/download/astral-regex-1.0.0.tgz",
+ "integrity": "sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/async-each/download/async-each-1.0.2.tgz",
+ "integrity": "sha1-i4p8oqZY+Sfp8wfW0aQvQZnw9zU=",
+ "dev": true
+ },
+ "async-foreach": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+ "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
+ },
+ "async-limiter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+ "dev": true
+ },
+ "async-validator": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
+ "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+ "requires": {
+ "babel-runtime": "6.x"
+ }
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz",
+ "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=",
+ "dev": true
+ },
+ "autoprefixer": {
+ "version": "9.5.1",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
+ "integrity": "sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.5.4",
+ "caniuse-lite": "^1.0.30000957",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.14",
+ "postcss-value-parser": "^3.3.1"
+ },
+ "dependencies": {
+ "browserslist": {
+ "version": "4.5.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz",
+ "integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000960",
+ "electron-to-chromium": "^1.3.124",
+ "node-releases": "^1.1.14"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000962",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000962.tgz",
+ "integrity": "sha512-WXYsW38HK+6eaj5IZR16Rn91TGhU3OhbwjKZvJ4HN/XBIABLKfbij9Mnd3pM0VEwZSlltWjoWg3I8FQ0DGgNOA==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.124",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz",
+ "integrity": "sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w==",
+ "dev": true
+ },
+ "node-releases": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.15.tgz",
+ "integrity": "sha512-cKV097BQaZr8LTSRUa2+oc/aX5L8UkZtPQrMSTgiJEeaW7ymTDCoRaGCoaTqk0lqnalcoSHu4wjSl0Cmj2+bMw==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ }
+ }
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.8.0.tgz",
+ "integrity": "sha1-8OAD2cqef1nHpQiUXXsu+aBKVC8="
+ },
+ "axios": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
+ "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
+ "requires": {
+ "follow-redirects": "1.5.10",
+ "is-buffer": "^2.0.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+ "requires": {
+ "debug": "=3.1.0"
+ }
+ },
+ "is-buffer": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
+ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "http://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "babel-eslint": {
+ "version": "10.0.1",
+ "resolved": "http://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.0.1.tgz",
+ "integrity": "sha1-kZaB3AmWFM19MdRciQhpUJKh+u0=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.0.0",
+ "@babel/traverse": "^7.0.0",
+ "@babel/types": "^7.0.0",
+ "eslint-scope": "3.7.1",
+ "eslint-visitor-keys": "^1.0.0"
+ },
+ "dependencies": {
+ "eslint-scope": {
+ "version": "3.7.1",
+ "resolved": "http://registry.npm.taobao.org/eslint-scope/download/eslint-scope-3.7.1.tgz",
+ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ }
+ }
+ },
+ "babel-helper-vue-jsx-merge-props": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+ "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+ },
+ "babel-loader": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz",
+ "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==",
+ "dev": true,
+ "requires": {
+ "find-cache-dir": "^2.1.0",
+ "loader-utils": "^1.4.0",
+ "mkdirp": "^0.5.3",
+ "pify": "^4.0.1",
+ "schema-utils": "^2.6.5"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
+ "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
+ "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+ "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "schema-utils": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
+ "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.0",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.2.0.tgz",
+ "integrity": "sha1-wK37B9lfSkSV6aqsbsOGxNfCUk4=",
+ "dev": true,
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "http://registry.npm.taobao.org/base/download/base-0.11.2.tgz",
+ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-js": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npm.taobao.org/base64-js/download/base64-js-1.3.0.tgz",
+ "integrity": "sha1-yrHmEY8FEJXli1KBrqjBzSK/wOM=",
+ "dev": true
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "http://registry.npm.taobao.org/batch/download/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "bfj": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.1.tgz",
+ "integrity": "sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "check-types": "^7.3.0",
+ "hoopy": "^0.1.2",
+ "tryer": "^1.0.0"
+ }
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "http://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz",
+ "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg="
+ },
+ "binary-extensions": {
+ "version": "1.13.0",
+ "resolved": "http://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.0.tgz",
+ "integrity": "sha1-lSPgATBqMkRLkHQj8d4hZCIvarE=",
+ "dev": true
+ },
+ "bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+ "requires": {
+ "inherits": "~2.0.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.3",
+ "resolved": "http://registry.npm.taobao.org/bluebird/download/bluebird-3.5.3.tgz",
+ "integrity": "sha1-fQHG+WFsmlGrD4xUmnnf5uwz76c=",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "http://registry.npm.taobao.org/bn.js/download/bn.js-4.11.8.tgz",
+ "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.18.3",
+ "resolved": "http://registry.npm.taobao.org/body-parser/download/body-parser-1.18.3.tgz",
+ "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "~1.6.3",
+ "iconv-lite": "0.4.23",
+ "on-finished": "~2.3.0",
+ "qs": "6.5.2",
+ "raw-body": "2.3.3",
+ "type-is": "~1.6.16"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "http://registry.npm.taobao.org/bonjour/download/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": true
+ }
+ }
+ },
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/boolbase/download/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+ "dev": true
+ },
+ "bootstrap": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz",
+ "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag=="
+ },
+ "bootstrap-vue": {
+ "version": "2.0.0-rc.19",
+ "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.0.0-rc.19.tgz",
+ "integrity": "sha512-OCbRwqKb0F+RGr162m+RyKI4yNM0VjfxOGI32CMgHfCnnc0MZ0wF2Svg2E3Q7AWCq0N8LgD/EsF/K7Vg3kdDyw==",
+ "requires": {
+ "@nuxt/opencollective": "^0.2.2",
+ "bootstrap": "^4.3.1",
+ "core-js": ">=2.6.5 <3.0.0",
+ "popper.js": "^1.15.0",
+ "portal-vue": "^2.1.1",
+ "vue-functional-data-merge": "^2.0.7"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz",
+ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "http://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz",
+ "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/brorand/download/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/browserify-aes/download/browserify-aes-1.2.0.tgz",
+ "integrity": "sha1-Mmc0ZC9APavDADIJhTu3CtQo70g=",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/browserify-cipher/download/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha1-jWR0wbhwv9q807z8wZNKEOlPFfA=",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/browserify-des/download/browserify-des-1.0.2.tgz",
+ "integrity": "sha1-OvTx9Zg5QDVy8cZiBDdfen9wPpw=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "http://registry.npm.taobao.org/browserify-rsa/download/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "http://registry.npm.taobao.org/browserify-sign/download/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/browserify-zlib/download/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=",
+ "dev": true,
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.5.2",
+ "resolved": "http://registry.npm.taobao.org/browserslist/download/browserslist-4.5.2.tgz",
+ "integrity": "sha1-Nq0oHwQK9oRVWiPHgPXCCBx1LfA=",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000951",
+ "electron-to-chromium": "^1.3.116",
+ "node-releases": "^1.1.11"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "http://registry.npm.taobao.org/buffer/download/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz",
+ "integrity": "sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8=",
+ "dev": true
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/buffer-xor/download/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/builtin-status-codes/download/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz",
+ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "cache-loader": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-2.0.1.tgz",
+ "integrity": "sha512-V99T3FOynmGx26Zom+JrVBytLBsmUCzVG2/4NnUKgvXN4bEV42R1ERl1IyiH/cvFIDA1Ytq2lPZ9tXDSahcQpQ==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "mkdirp": "^0.5.1",
+ "neo-async": "^2.6.0",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "call-me-maybe": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/call-me-maybe/download/call-me-maybe-1.0.1.tgz",
+ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
+ "dev": true
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/caller-callsite/download/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ }
+ }
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "http://registry.npm.taobao.org/caller-path/download/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "callsites": "^0.2.0"
+ }
+ },
+ "callsites": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/callsites/download/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+ "dev": true,
+ "optional": true
+ },
+ "camel-case": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/camel-case/download/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "dev": true,
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "camelcase": {
+ "version": "5.2.0",
+ "resolved": "http://registry.npm.taobao.org/camelcase/download/camelcase-5.2.0.tgz",
+ "integrity": "sha1-51IqvaXtlMwEieG4RmYQ6IQEz0U=",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+ "requires": {
+ "camelcase": "^2.0.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+ "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
+ }
+ }
+ },
+ "caniuse-api": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-lite": "^1.0.0",
+ "lodash.memoize": "^4.1.2",
+ "lodash.uniq": "^4.5.0"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000951",
+ "resolved": "http://registry.npm.taobao.org/caniuse-lite/download/caniuse-lite-1.0.30000951.tgz",
+ "integrity": "sha1-x8L9TXEIAoTIZ33UEDaN+Ng2iP4=",
+ "dev": true
+ },
+ "case-sensitive-paths-webpack-plugin": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz",
+ "integrity": "sha512-u5ElzokS8A1pm9vM3/iDgTcI3xqHxuCao94Oz8etI3cf0Tio0p8izkDYbTIn09uP3yUUr6+veaE6IkjnTYS46g==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "http://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz",
+ "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=",
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chardet": {
+ "version": "0.4.2",
+ "resolved": "http://registry.npm.taobao.org/chardet/download/chardet-0.4.2.tgz",
+ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
+ "dev": true,
+ "optional": true
+ },
+ "chart.js": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.8.0.tgz",
+ "integrity": "sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==",
+ "requires": {
+ "chartjs-color": "^2.1.0",
+ "moment": "^2.10.2"
+ }
+ },
+ "chartjs-color": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.3.0.tgz",
+ "integrity": "sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==",
+ "requires": {
+ "chartjs-color-string": "^0.6.0",
+ "color-convert": "^0.5.3"
+ },
+ "dependencies": {
+ "color-convert": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
+ "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
+ }
+ }
+ },
+ "chartjs-color-string": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
+ "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
+ "requires": {
+ "color-name": "^1.0.0"
+ }
+ },
+ "check-types": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/check-types/-/check-types-7.4.0.tgz",
+ "integrity": "sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/chokidar/download/chokidar-2.1.2.tgz",
+ "integrity": "sha1-nCPqQLAWOEOeBROGTTYq6sxa0Fg=",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.0"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/chownr/download/chownr-1.1.1.tgz",
+ "integrity": "sha1-VHJri4//TfBTxCGH6AH7RBLfFJQ="
+ },
+ "chrome-trace-event": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/chrome-trace-event/download/chrome-trace-event-1.0.0.tgz",
+ "integrity": "sha1-Rakb0sIMlBHwljtarrmhuV4JzEg=",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "ci-info": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
+ "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/cipher-base/download/cipher-base-1.0.4.tgz",
+ "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "http://registry.npm.taobao.org/circular-json/download/circular-json-0.3.3.tgz",
+ "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=",
+ "dev": true,
+ "optional": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "http://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz",
+ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-css": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^2.0.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/cli-spinners/download/cli-spinners-2.0.0.tgz",
+ "integrity": "sha1-SweHVvwXqPcgQ/3J8fFL9PqH4t8=",
+ "dev": true
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/cli-width/download/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "clipboard": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz",
+ "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==",
+ "requires": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
+ "clipboardy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.0.0.tgz",
+ "integrity": "sha512-XbVjHMsss0giNUkp/tV/3eEAZe8i1fZTLzmPKqjE1RGIAWOTiF5D014f6R+g53ZAq0IK3cPrJXFvqE8eQjhFYQ==",
+ "dev": true,
+ "requires": {
+ "arch": "^2.1.1",
+ "execa": "^1.0.0"
+ }
+ },
+ "cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dev": true,
+ "requires": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/clone/download/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
+ "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
+ "requires": {
+ "for-own": "^1.0.0",
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.0",
+ "shallow-clone": "^1.0.0"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "http://registry.npm.taobao.org/co/download/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "coa": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+ "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
+ "dev": true,
+ "requires": {
+ "@types/q": "^1.5.1",
+ "chalk": "^2.4.1",
+ "q": "^1.1.2"
+ }
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.1.0.tgz",
+ "integrity": "sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.1",
+ "color-string": "^1.5.2"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "http://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz",
+ "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "color-string": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.7",
+ "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.7.tgz",
+ "integrity": "sha1-LR0kMXr7ir6V1tLAsHtXgTU52Cg=",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.19.0",
+ "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz",
+ "integrity": "sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "http://registry.npm.taobao.org/component-emitter/download/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "compressible": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz",
+ "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==",
+ "dev": true,
+ "requires": {
+ "mime-db": ">= 1.38.0 < 2"
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "http://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz",
+ "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true
+ },
+ "consola": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/consola/-/consola-2.6.1.tgz",
+ "integrity": "sha512-vt35owQG6OxYDJVaViQ4aFgOK+b98hIvs+R5CWkKgpO8rTPyaYwlMadZ7oZcjnWz1/+u4czDnrcogFr5AtrRug=="
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/console-browserify/download/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "dev": true,
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+ },
+ "consolidate": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
+ "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.1.1"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/constants-browserify/download/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "http://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.6.0",
+ "resolved": "http://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.6.0.tgz",
+ "integrity": "sha1-UbU3qMQ+DwTewZk7/83VBOdYrCA=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "http://registry.npm.taobao.org/cookie/download/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "http://registry.npm.taobao.org/cookie-signature/download/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/copy-concurrently/download/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha1-kilzmMrjSTf8r9bsgTnBgFHwteA=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "copy-webpack-plugin": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz",
+ "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^10.0.4",
+ "find-cache-dir": "^1.0.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.0",
+ "loader-utils": "^1.1.0",
+ "minimatch": "^3.0.4",
+ "p-limit": "^1.0.0",
+ "serialize-javascript": "^1.4.0"
+ },
+ "dependencies": {
+ "cacache": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+ "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.1",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.2",
+ "ssri": "^5.2.4",
+ "unique-filename": "^1.1.0",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-1.0.0.tgz",
+ "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^1.0.0",
+ "pkg-dir": "^2.0.0"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "http://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "mississippi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz",
+ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^2.0.1",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz",
+ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "ssri": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz",
+ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "core-js": {
+ "version": "2.6.5",
+ "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-2.6.5.tgz",
+ "integrity": "sha1-RLyNJJ5/sv9dAOA0Gn/7lPv2eJU="
+ },
+ "core-js-compat": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/core-js-compat/download/core-js-compat-3.0.0.tgz",
+ "integrity": "sha1-zZgQuAAHQlNaSkN3OGYYXjEL1Pc=",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.5.1",
+ "core-js": "3.0.0",
+ "core-js-pure": "3.0.0",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/core-js/download/core-js-3.0.0.tgz",
+ "integrity": "sha1-qNv6l40pv8Jjv7ZsVW0MqSTCiVc=",
+ "dev": true
+ }
+ }
+ },
+ "core-js-pure": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/core-js-pure/download/core-js-pure-3.0.0.tgz",
+ "integrity": "sha1-pWea20h1QnyMBIivyT5vW3ElhZs=",
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "cosmiconfig": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
+ "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
+ "dev": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.0",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "http://registry.npm.taobao.org/create-ecdh/download/create-ecdh-4.0.3.tgz",
+ "integrity": "sha1-yREbbzMEXEaX8UR4f5JUzcd8Rf8=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/create-hash/download/create-hash-1.2.0.tgz",
+ "integrity": "sha1-iJB4rxGmN1a8+1m9IhmWvjqe8ZY=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "http://registry.npm.taobao.org/create-hmac/download/create-hmac-1.1.7.tgz",
+ "integrity": "sha1-aRcMeLOrlXFHsriwRXLkfq0iQ/8=",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz",
+ "integrity": "sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q=",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "http://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=",
+ "dev": true,
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "css-color-names": {
+ "version": "0.0.4",
+ "resolved": "http://registry.npm.taobao.org/css-color-names/download/css-color-names-0.0.4.tgz",
+ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
+ "dev": true
+ },
+ "css-declaration-sorter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
+ "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.1",
+ "timsort": "^0.3.0"
+ }
+ },
+ "css-loader": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz",
+ "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.26.0",
+ "css-selector-tokenizer": "^0.7.0",
+ "icss-utils": "^2.1.0",
+ "loader-utils": "^1.0.2",
+ "lodash": "^4.17.11",
+ "postcss": "^6.0.23",
+ "postcss-modules-extract-imports": "^1.2.0",
+ "postcss-modules-local-by-default": "^1.2.0",
+ "postcss-modules-scope": "^1.1.0",
+ "postcss-modules-values": "^1.3.0",
+ "postcss-value-parser": "^3.3.0",
+ "source-list-map": "^2.0.0"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "css-select": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz",
+ "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==",
+ "dev": true,
+ "requires": {
+ "boolbase": "^1.0.0",
+ "css-what": "^2.1.2",
+ "domutils": "^1.7.0",
+ "nth-check": "^1.0.2"
+ }
+ },
+ "css-select-base-adapter": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+ "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
+ "dev": true
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+ "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^0.1.0",
+ "fastparse": "^1.1.1",
+ "regexpu-core": "^1.0.0"
+ },
+ "dependencies": {
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "http://registry.npm.taobao.org/cssesc/download/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/regexpu-core/download/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/regjsgen/download/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "http://registry.npm.taobao.org/regjsparser/download/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ }
+ }
+ }
+ },
+ "css-unit-converter": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/css-unit-converter/download/css-unit-converter-1.1.1.tgz",
+ "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=",
+ "dev": true
+ },
+ "css-what": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+ "dev": true
+ },
+ "cssesc": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
+ "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==",
+ "dev": true
+ },
+ "cssnano": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz",
+ "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "cssnano-preset-default": "^4.0.7",
+ "is-resolvable": "^1.0.0",
+ "postcss": "^7.0.0"
+ }
+ },
+ "cssnano-preset-default": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz",
+ "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==",
+ "dev": true,
+ "requires": {
+ "css-declaration-sorter": "^4.0.1",
+ "cssnano-util-raw-cache": "^4.0.1",
+ "postcss": "^7.0.0",
+ "postcss-calc": "^7.0.1",
+ "postcss-colormin": "^4.0.3",
+ "postcss-convert-values": "^4.0.1",
+ "postcss-discard-comments": "^4.0.2",
+ "postcss-discard-duplicates": "^4.0.2",
+ "postcss-discard-empty": "^4.0.1",
+ "postcss-discard-overridden": "^4.0.1",
+ "postcss-merge-longhand": "^4.0.11",
+ "postcss-merge-rules": "^4.0.3",
+ "postcss-minify-font-values": "^4.0.2",
+ "postcss-minify-gradients": "^4.0.2",
+ "postcss-minify-params": "^4.0.2",
+ "postcss-minify-selectors": "^4.0.2",
+ "postcss-normalize-charset": "^4.0.1",
+ "postcss-normalize-display-values": "^4.0.2",
+ "postcss-normalize-positions": "^4.0.2",
+ "postcss-normalize-repeat-style": "^4.0.2",
+ "postcss-normalize-string": "^4.0.2",
+ "postcss-normalize-timing-functions": "^4.0.2",
+ "postcss-normalize-unicode": "^4.0.1",
+ "postcss-normalize-url": "^4.0.1",
+ "postcss-normalize-whitespace": "^4.0.2",
+ "postcss-ordered-values": "^4.1.2",
+ "postcss-reduce-initial": "^4.0.3",
+ "postcss-reduce-transforms": "^4.0.2",
+ "postcss-svgo": "^4.0.2",
+ "postcss-unique-selectors": "^4.0.1"
+ }
+ },
+ "cssnano-util-get-arguments": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/cssnano-util-get-arguments/download/cssnano-util-get-arguments-4.0.0.tgz",
+ "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
+ "dev": true
+ },
+ "cssnano-util-get-match": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/cssnano-util-get-match/download/cssnano-util-get-match-4.0.0.tgz",
+ "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
+ "dev": true
+ },
+ "cssnano-util-raw-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
+ "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "cssnano-util-same-parent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
+ "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
+ "dev": true
+ },
+ "current-script-polyfill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/current-script-polyfill/-/current-script-polyfill-1.0.0.tgz",
+ "integrity": "sha1-8xz35PPiGLBybnOMqSoC00iO9hU=",
+ "dev": true
+ },
+ "currently-unhandled": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+ "requires": {
+ "array-find-index": "^1.0.1"
+ }
+ },
+ "cyclist": {
+ "version": "0.2.2",
+ "resolved": "http://registry.npm.taobao.org/cyclist/download/cyclist-0.2.2.tgz",
+ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "http://registry.npm.taobao.org/date-now/download/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+ "dev": true
+ },
+ "de-indent": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/de-indent/download/de-indent-1.0.2.tgz",
+ "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz",
+ "integrity": "sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/deep-equal/download/deep-equal-1.0.1.tgz",
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+ "dev": true
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "http://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "deepmerge": {
+ "version": "1.5.2",
+ "resolved": "http://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
+ "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
+ },
+ "default-gateway": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
+ "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "defaults": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz",
+ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
+ "dev": true,
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz",
+ "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz",
+ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/des.js/download/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "http://registry.npm.taobao.org/diffie-hellman/download/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha1-QOjumPVaIUlgcUaSHGPhrl89KHU=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "http://registry.npm.taobao.org/dir-glob/download/dir-glob-2.2.2.tgz",
+ "integrity": "sha1-+gnwaUFTyJGLGLoN6vrpR2n8UMQ=",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/dns-equal/download/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/dns-txt/download/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/doctrine/download/doctrine-2.1.0.tgz",
+ "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "requires": {
+ "utila": "~0.4"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+ "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.0",
+ "entities": "^1.1.1"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz",
+ "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=",
+ "dev": true
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+ "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+ "dev": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "dotenv": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz",
+ "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==",
+ "dev": true
+ },
+ "dotenv-expand": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
+ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
+ "dev": true
+ },
+ "downloadjs": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/downloadjs/-/downloadjs-1.4.7.tgz",
+ "integrity": "sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw="
+ },
+ "duplexer": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/duplexer/download/duplexer-0.1.1.tgz",
+ "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "http://registry.npm.taobao.org/duplexify/download/duplexify-3.7.1.tgz",
+ "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "easy-stack": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/easy-stack/download/easy-stack-1.0.0.tgz",
+ "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=",
+ "dev": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "echarts": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/echarts/-/echarts-4.6.0.tgz",
+ "integrity": "sha512-xKkcr6v9UVOSF+PMuj7Ngt3bnzLwN1sSXWCvpvX+jYb3mePYsZnABq7wGkPac/m0nV653uGHXoHK8DCKCprdNg==",
+ "requires": {
+ "zrender": "4.2.0"
+ }
+ },
+ "echarts-amap": {
+ "version": "1.0.0-rc.6",
+ "resolved": "https://registry.npmjs.org/echarts-amap/-/echarts-amap-1.0.0-rc.6.tgz",
+ "integrity": "sha1-V4KnTa7lLtRM4/j2JXdWF4PwnhY="
+ },
+ "echarts-liquidfill": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/echarts-liquidfill/-/echarts-liquidfill-2.0.5.tgz",
+ "integrity": "sha512-3G19W5ngoh1L3BXYuD34g0Vd30ORWvQtyxRuL+7vmOZ3FkF6xkgD4pfcCL7QVAQOr+XZ4OiD2ot6dNGsRhflcg=="
+ },
+ "echarts-wordcloud": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-1.1.3.tgz",
+ "integrity": "sha512-Et8D5xEAoYkidmHun+hEH+2lF9dhCt6D0JJ390vlr2r/1zwhhZAbcL01CEvG93QcMcJpSvSPK8vRiGkTbMHRxg=="
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "ejs": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz",
+ "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.119",
+ "resolved": "http://registry.npm.taobao.org/electron-to-chromium/download/electron-to-chromium-1.3.119.tgz",
+ "integrity": "sha1-mndw2mZyUq64H2Z4U/Z8KybgAZc=",
+ "dev": true
+ },
+ "element-ui": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.13.1.tgz",
+ "integrity": "sha512-jyvJmXa2c6ElRc4NOw4V1vnjHsvfzTRhbwElZ68CyF9by2F64B+AJRzujg/HJgXCimHwd2g1Av9D04EP3mWymg==",
+ "requires": {
+ "async-validator": "~1.8.1",
+ "babel-helper-vue-jsx-merge-props": "^2.0.0",
+ "deepmerge": "^1.2.0",
+ "normalize-wheel": "^1.0.1",
+ "resize-observer-polyfill": "^1.5.0",
+ "throttle-debounce": "^1.0.1"
+ }
+ },
+ "elliptic": {
+ "version": "6.4.1",
+ "resolved": "http://registry.npm.taobao.org/elliptic/download/elliptic-6.4.1.tgz",
+ "integrity": "sha1-wtC3d2kRuGcixjLDwGxg8vgZk5o=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "http://registry.npm.taobao.org/emoji-regex/download/emoji-regex-7.0.3.tgz",
+ "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/emojis-list/download/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "http://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.1.tgz",
+ "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "http://registry.npm.taobao.org/enhanced-resolve/download/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha1-Qcfgv9/nSsH/4eV61qXGyfN0Kn8=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "http://registry.npm.taobao.org/errno/download/errno-0.1.7.tgz",
+ "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "error-stack-parser": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz",
+ "integrity": "sha512-E1fPutRDdIj/hohG0UpT5mayXNCxXP9d+snxFsPU9X0XgccOumKraa3juDMwTUyi7+Bu5+mCGagjg4IYeNbOdw==",
+ "dev": true,
+ "requires": {
+ "stackframe": "^1.0.4"
+ }
+ },
+ "es-abstract": {
+ "version": "1.13.0",
+ "resolved": "http://registry.npm.taobao.org/es-abstract/download/es-abstract-1.13.0.tgz",
+ "integrity": "sha1-rIYUX91QmdjdSVWMy6Lq+biOJOk=",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-keys": "^1.0.12"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha1-7fckeAM0VujdqO8J4ArZZQcH83c=",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "eslint": {
+ "version": "5.15.3",
+ "resolved": "http://registry.npm.taobao.org/eslint/download/eslint-5.15.3.tgz",
+ "integrity": "sha1-x5w5CdyKf6NxT7NAwR4w/SUmuLU=",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.9.1",
+ "chalk": "^2.1.0",
+ "cross-spawn": "^6.0.5",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^4.0.3",
+ "eslint-utils": "^1.3.1",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^5.0.1",
+ "esquery": "^1.0.1",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^5.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob": "^7.1.2",
+ "globals": "^11.7.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^6.2.2",
+ "js-yaml": "^3.12.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.11",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.2",
+ "path-is-inside": "^1.0.2",
+ "progress": "^2.0.0",
+ "regexpp": "^2.0.1",
+ "semver": "^5.5.1",
+ "strip-ansi": "^4.0.0",
+ "strip-json-comments": "^2.0.1",
+ "table": "^5.2.3",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.0.1",
+ "resolved": "http://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.0.1.tgz",
+ "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=",
+ "dev": true
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "http://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz",
+ "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=",
+ "dev": true
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/doctrine/download/doctrine-3.0.0.tgz",
+ "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "espree": {
+ "version": "5.0.1",
+ "resolved": "http://registry.npm.taobao.org/espree/download/espree-5.0.1.tgz",
+ "integrity": "sha1-XWUm+k/H8HiKXPdbFfMDI+L4H3o=",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.7",
+ "acorn-jsx": "^5.0.0",
+ "eslint-visitor-keys": "^1.0.0"
+ }
+ },
+ "external-editor": {
+ "version": "3.0.3",
+ "resolved": "http://registry.npm.taobao.org/external-editor/download/external-editor-3.0.3.tgz",
+ "integrity": "sha1-WGbbKal4Jtvkvzr9JAcOrZ6kOic=",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "file-entry-cache": {
+ "version": "5.0.1",
+ "resolved": "http://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-5.0.1.tgz",
+ "integrity": "sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w=",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^2.0.1"
+ }
+ },
+ "flat-cache": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/flat-cache/download/flat-cache-2.0.1.tgz",
+ "integrity": "sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA=",
+ "dev": true,
+ "requires": {
+ "flatted": "^2.0.0",
+ "rimraf": "2.6.3",
+ "write": "1.0.3"
+ }
+ },
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "http://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz",
+ "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/import-fresh/download/import-fresh-3.0.0.tgz",
+ "integrity": "sha1-o9iX9CDKsOZxI2iX91vBS0iFw5A=",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "inquirer": {
+ "version": "6.2.2",
+ "resolved": "http://registry.npm.taobao.org/inquirer/download/inquirer-6.2.2.tgz",
+ "integrity": "sha1-RpQRdvZcnrIIBGJxSbdDohjyVAY=",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^3.2.0",
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^2.0.0",
+ "lodash": "^4.17.11",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.4.0",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^5.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz",
+ "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "regexpp": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/regexpp/download/regexpp-2.0.1.tgz",
+ "integrity": "sha1-jRnTHPYySCtYkEn4KB+T28uk0H8=",
+ "dev": true
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-4.0.0.tgz",
+ "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/slice-ansi/download/slice-ansi-2.1.0.tgz",
+ "integrity": "sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "astral-regex": "^1.0.0",
+ "is-fullwidth-code-point": "^2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "table": {
+ "version": "5.2.3",
+ "resolved": "http://registry.npm.taobao.org/table/download/table-5.2.3.tgz",
+ "integrity": "sha1-zeDMbrBnUcAJ76sn6Mggyltnt/I=",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.9.1",
+ "lodash": "^4.17.11",
+ "slice-ansi": "^2.1.0",
+ "string-width": "^3.0.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-3.1.0.tgz",
+ "integrity": "sha1-InZ74htirxCBV0MG9prFG2IgOWE=",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz",
+ "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "write": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/write/download/write-1.0.3.tgz",
+ "integrity": "sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM=",
+ "dev": true,
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ }
+ }
+ },
+ "eslint-loader": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.2.1.tgz",
+ "integrity": "sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg==",
+ "dev": true,
+ "requires": {
+ "loader-fs-cache": "^1.0.0",
+ "loader-utils": "^1.0.2",
+ "object-assign": "^4.0.1",
+ "object-hash": "^1.1.4",
+ "rimraf": "^2.6.1"
+ }
+ },
+ "eslint-plugin-vue": {
+ "version": "5.2.2",
+ "resolved": "http://registry.npm.taobao.org/eslint-plugin-vue/download/eslint-plugin-vue-5.2.2.tgz",
+ "integrity": "sha1-hmAYI7dyG3C8ktVPFyjPwDs2KDw=",
+ "dev": true,
+ "requires": {
+ "vue-eslint-parser": "^5.0.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
+ "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.0.1",
+ "resolved": "http://registry.npm.taobao.org/acorn-jsx/download/acorn-jsx-5.0.1.tgz",
+ "integrity": "sha1-MqBk/ZJUKSFqCbFBECv90YX65A4=",
+ "dev": true
+ },
+ "espree": {
+ "version": "4.1.0",
+ "resolved": "http://registry.npm.taobao.org/espree/download/espree-4.1.0.tgz",
+ "integrity": "sha1-co1UUeD9FWwEOEp62J7VH/VOsl8=",
+ "dev": true,
+ "requires": {
+ "acorn": "^6.0.2",
+ "acorn-jsx": "^5.0.0",
+ "eslint-visitor-keys": "^1.0.0"
+ }
+ },
+ "vue-eslint-parser": {
+ "version": "5.0.0",
+ "resolved": "http://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-5.0.0.tgz",
+ "integrity": "sha1-APTk2pTsl0uCGib/DtD3p4QCuKE=",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^4.1.0",
+ "esquery": "^1.0.1",
+ "lodash": "^4.17.11"
+ }
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "4.0.3",
+ "resolved": "http://registry.npm.taobao.org/eslint-scope/download/eslint-scope-4.0.3.tgz",
+ "integrity": "sha1-ygODMxD2iJoyZHgaqC5j65z+eEg=",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "eslint-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/eslint-visitor-keys/download/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=",
+ "dev": true
+ },
+ "espree": {
+ "version": "3.5.4",
+ "resolved": "http://registry.npm.taobao.org/espree/download/espree-3.5.4.tgz",
+ "integrity": "sha1-sPRHGHyKi+2US4FaZgvd9d610ac=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "acorn": "^5.5.0",
+ "acorn-jsx": "^3.0.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/esquery/download/esquery-1.0.1.tgz",
+ "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=",
+ "dev": true,
+ "requires": {
+ "estraverse": "^4.0.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "http://registry.npm.taobao.org/esrecurse/download/esrecurse-4.2.1.tgz",
+ "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=",
+ "dev": true,
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "http://registry.npm.taobao.org/estraverse/download/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/esutils/download/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "http://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "event-pubsub": {
+ "version": "4.3.0",
+ "resolved": "http://registry.npm.taobao.org/event-pubsub/download/event-pubsub-4.3.0.tgz",
+ "integrity": "sha1-9o2Ba8KfHsAsU53FjI3UDOcss24=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
+ "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
+ "dev": true
+ },
+ "events": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/events/download/events-3.0.0.tgz",
+ "integrity": "sha1-mgoN+vYok9krh1uPJpjKQRSXPog=",
+ "dev": true
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "dev": true,
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/evp_bytestokey/download/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=",
+ "dev": true,
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz",
+ "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "http://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "express": {
+ "version": "4.16.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+ "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.18.3",
+ "content-disposition": "0.5.2",
+ "content-type": "~1.0.4",
+ "cookie": "0.3.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.1.1",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.4",
+ "qs": "6.5.2",
+ "range-parser": "~1.2.0",
+ "safe-buffer": "5.1.2",
+ "send": "0.16.2",
+ "serve-static": "1.13.2",
+ "setprototypeof": "1.1.0",
+ "statuses": "~1.4.0",
+ "type-is": "~1.6.16",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "http://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz",
+ "integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo="
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz",
+ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/external-editor/download/external-editor-2.2.0.tgz",
+ "integrity": "sha1-BFURz9jRM/OEZnPRBHwVTiFK09U=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chardet": "^0.4.0",
+ "iconv-lite": "^0.4.17",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "http://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz",
+ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
+ },
+ "fast-glob": {
+ "version": "2.2.6",
+ "resolved": "http://registry.npm.taobao.org/fast-glob/download/fast-glob-2.2.6.tgz",
+ "integrity": "sha1-pdW2l+yN7aRo2Fp0A1KQoCWpUpU=",
+ "dev": true,
+ "requires": {
+ "@mrmlnc/readdir-enhanced": "^2.2.1",
+ "@nodelib/fs.stat": "^1.1.2",
+ "glob-parent": "^3.1.0",
+ "is-glob": "^4.0.0",
+ "merge2": "^1.2.3",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "http://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "http://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "resolved": "http://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.1.tgz",
+ "integrity": "sha1-hiRwESkBxyeg5JWoB0S9W6odZ5A=",
+ "dev": true
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/figures/download/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/file-entry-cache/download/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "flat-cache": "^1.2.1",
+ "object-assign": "^4.0.1"
+ }
+ },
+ "file-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
+ "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "dev": true,
+ "optional": true
+ },
+ "filesize": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
+ "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+ "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.2",
+ "statuses": "~1.4.0",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz",
+ "integrity": "sha1-SRafHXmTQwZG2mHsxa41XCHJe3M=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.4",
+ "resolved": "http://registry.npm.taobao.org/flat-cache/download/flat-cache-1.3.4.tgz",
+ "integrity": "sha1-LC73dSXMKSkAff/6HdMUqpyd7m8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "circular-json": "^0.3.1",
+ "graceful-fs": "^4.1.2",
+ "rimraf": "~2.6.2",
+ "write": "^0.2.1"
+ }
+ },
+ "flatted": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/flatted/download/flatted-2.0.0.tgz",
+ "integrity": "sha1-VRIrZTbqSWtLRIk+4mCBQdENmRY=",
+ "dev": true
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/flush-write-stream/download/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha1-jdfYc6G6vCB9lOrQwuDkQnbr8ug=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.7.0",
+ "resolved": "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.7.0.tgz",
+ "integrity": "sha1-SJ68GY3A5/ZBZ70jsDxMGbV4THY=",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.6"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz",
+ "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "font-awesome": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+ "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "requires": {
+ "for-in": "^1.0.1"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz",
+ "integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "http://registry.npm.taobao.org/forwarded/download/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "http://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "http://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
+ "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "http://registry.npm.taobao.org/fs-write-stream-atomic/download/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz",
+ "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1",
+ "node-pre-gyp": "*"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "3.2.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.9.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.3.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.9.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.14.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4.4.2"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "npm-normalize-package-bin": "^1.0.1"
+ }
+ },
+ "npm-normalize-package-bin": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.13",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.8.6",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.1.1",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
+ }
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz",
+ "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "gaze": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+ "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+ "requires": {
+ "globule": "^1.0.0"
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+ },
+ "get-stdin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz",
+ "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "http://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "resolved": "http://registry.npm.taobao.org/glob/download/glob-7.1.3.tgz",
+ "integrity": "sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE=",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "http://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "glob-to-regexp": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/glob-to-regexp/download/glob-to-regexp-0.3.0.tgz",
+ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
+ "dev": true
+ },
+ "globals": {
+ "version": "11.11.0",
+ "resolved": "http://registry.npm.taobao.org/globals/download/globals-11.11.0.tgz",
+ "integrity": "sha1-3Pk3V/ot5Uhvvu1xGFOK33ienC4=",
+ "dev": true
+ },
+ "globby": {
+ "version": "9.1.0",
+ "resolved": "http://registry.npm.taobao.org/globby/download/globby-9.1.0.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fglobby%2Fdownload%2Fglobby-9.1.0.tgz",
+ "integrity": "sha1-6Q9NUTQQnm2FWr3TG9sbCFQoWS4=",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^1.0.2",
+ "dir-glob": "^2.2.1",
+ "fast-glob": "^2.2.6",
+ "glob": "^7.1.3",
+ "ignore": "^4.0.3",
+ "pify": "^4.0.1",
+ "slash": "^2.0.0"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "http://registry.npm.taobao.org/ignore/download/ignore-4.0.6.tgz",
+ "integrity": "sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw=",
+ "dev": true
+ }
+ }
+ },
+ "globule": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz",
+ "integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==",
+ "requires": {
+ "glob": "~7.1.1",
+ "lodash": "~4.17.12",
+ "minimatch": "~3.0.2"
+ }
+ },
+ "good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "requires": {
+ "delegate": "^3.1.2"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.15",
+ "resolved": "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.15.tgz",
+ "integrity": "sha1-/7cD4QZuig7qpMi4C6klPu77+wA="
+ },
+ "gzip-size": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.0.tgz",
+ "integrity": "sha512-wfSnvypBDRW94v5W3ckvvz/zFUNdJ81VgOP6tE4bPpRUcc0wGqU+y0eZjJEvKxwubJFix6P84sE8M51YWLT7rQ==",
+ "dev": true,
+ "requires": {
+ "duplexer": "^0.1.1",
+ "pify": "^4.0.1"
+ }
+ },
+ "handle-thing": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
+ "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==",
+ "dev": true
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz",
+ "integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=",
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/has/download/has-1.0.3.tgz",
+ "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ }
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "http://registry.npm.taobao.org/hash-base/download/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash-sum": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz",
+ "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
+ "dev": true
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "http://registry.npm.taobao.org/hash.js/download/hash.js-1.1.7.tgz",
+ "integrity": "sha1-C6vKU46NTuSg+JiNaIZlN6ADz0I=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/he/download/he-1.2.0.tgz",
+ "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=",
+ "dev": true
+ },
+ "hex-color-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
+ "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
+ "dev": true
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/hmac-drbg/download/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true,
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hoek": {
+ "version": "6.1.2",
+ "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-6.1.2.tgz",
+ "integrity": "sha1-mebQcFYYOd507kJ7YapHa9a939Y=",
+ "dev": true
+ },
+ "hoopy": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
+ "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "http://registry.npm.taobao.org/hpack.js/download/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "hsl-regex": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/hsl-regex/download/hsl-regex-1.0.0.tgz",
+ "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
+ "dev": true
+ },
+ "hsla-regex": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/hsla-regex/download/hsla-regex-1.0.0.tgz",
+ "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
+ "dev": true
+ },
+ "html-comment-regex": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
+ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
+ "dev": true
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "http://registry.npm.taobao.org/html-entities/download/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "html-minifier": {
+ "version": "3.5.21",
+ "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
+ "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "dev": true,
+ "requires": {
+ "camel-case": "3.0.x",
+ "clean-css": "4.2.x",
+ "commander": "2.17.x",
+ "he": "1.2.x",
+ "param-case": "2.1.x",
+ "relateurl": "0.2.x",
+ "uglify-js": "3.4.x"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.17.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+ "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+ "dev": true
+ }
+ }
+ },
+ "html-tags": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/html-tags/download/html-tags-2.0.0.tgz",
+ "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
+ "dev": true
+ },
+ "html-webpack-plugin": {
+ "version": "3.2.0",
+ "resolved": "http://registry.npm.taobao.org/html-webpack-plugin/download/html-webpack-plugin-3.2.0.tgz",
+ "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
+ "dev": true,
+ "requires": {
+ "html-minifier": "^3.2.3",
+ "loader-utils": "^0.2.16",
+ "lodash": "^4.17.3",
+ "pretty-error": "^2.0.2",
+ "tapable": "^1.0.0",
+ "toposort": "^1.0.0",
+ "util.promisify": "1.0.0"
+ },
+ "dependencies": {
+ "big.js": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "http://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "0.2.17",
+ "resolved": "http://registry.npm.taobao.org/loader-utils/download/loader-utils-0.2.17.tgz",
+ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
+ "dev": true,
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0",
+ "object-assign": "^4.0.1"
+ }
+ }
+ }
+ },
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+ "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "http://registry.npm.taobao.org/http-deceiver/download/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "http://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "http-parser-js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz",
+ "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
+ "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^3.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
+ "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+ "dev": true,
+ "requires": {
+ "http-proxy": "^1.17.0",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.11",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/https-browserify/download/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "http://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz",
+ "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "icss-replace-symbols": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/icss-replace-symbols/download/icss-replace-symbols-1.1.0.tgz",
+ "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+ "dev": true
+ },
+ "icss-utils": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/icss-utils/download/icss-utils-2.1.0.tgz",
+ "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=",
+ "dev": true,
+ "requires": {
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "ieee754": {
+ "version": "1.1.12",
+ "resolved": "http://registry.npm.taobao.org/ieee754/download/ieee754-1.1.12.tgz",
+ "integrity": "sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs=",
+ "dev": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "http://registry.npm.taobao.org/iferr/download/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "http://registry.npm.taobao.org/ignore/download/ignore-3.3.10.tgz",
+ "integrity": "sha1-Cpf7h2mG6AgcYxFg+PnziRV/AEM=",
+ "dev": true
+ },
+ "import-cwd": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/import-cwd/download/import-cwd-2.1.0.tgz",
+ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+ "dev": true,
+ "requires": {
+ "import-from": "^2.1.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "dev": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ },
+ "dependencies": {
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "dev": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ }
+ }
+ },
+ "import-from": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/import-from/download/import-from-2.1.0.tgz",
+ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ }
+ }
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "http://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "in-publish": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz",
+ "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ=="
+ },
+ "indent-string": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
+ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "indexes-of": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/indexes-of/download/indexes-of-1.0.1.tgz",
+ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
+ "dev": true
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "http://registry.npm.taobao.org/indexof/download/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "http://registry.npm.taobao.org/inquirer/download/inquirer-3.3.0.tgz",
+ "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-escapes": "^3.0.0",
+ "chalk": "^2.0.0",
+ "cli-cursor": "^2.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^2.0.4",
+ "figures": "^2.0.0",
+ "lodash": "^4.3.0",
+ "mute-stream": "0.0.7",
+ "run-async": "^2.2.0",
+ "rx-lite": "^4.0.8",
+ "rx-lite-aggregates": "^4.0.8",
+ "string-width": "^2.1.0",
+ "strip-ansi": "^4.0.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "internal-ip": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
+ "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
+ "dev": true,
+ "requires": {
+ "default-gateway": "^4.2.0",
+ "ipaddr.js": "^1.9.0"
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "http://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz",
+ "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "http://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+ "dev": true
+ },
+ "is-absolute-url": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-absolute-url/download/is-absolute-url-2.1.0.tgz",
+ "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "http://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "http://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz",
+ "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "http://registry.npm.taobao.org/is-callable/download/is-callable-1.1.4.tgz",
+ "integrity": "sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU=",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
+ "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^1.5.0"
+ }
+ },
+ "is-color-stop": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-color-stop/download/is-color-stop-1.1.0.tgz",
+ "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=",
+ "dev": true,
+ "requires": {
+ "css-color-names": "^0.0.4",
+ "hex-color-regex": "^1.1.0",
+ "hsl-regex": "^1.0.0",
+ "hsla-regex": "^1.0.0",
+ "rgb-regex": "^1.0.1",
+ "rgba-regex": "^1.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz",
+ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz",
+ "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
+ "dev": true
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "http://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
+ "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-glob/download/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.0.0.tgz",
+ "integrity": "sha512-m5dHHzpOXEiv18JEORttBO64UgTEypx99vCxQLjbBvGhOJxnTNglYoFXxwo6AbsQb79sqqycQEHv2hWkHZAijA==",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.0.0.tgz",
+ "integrity": "sha512-6Vz5Gc9s/sDA3JBVu0FzWufm8xaBsqy1zn8Q6gmvGP6nSDMw78aS4poBNeatWjaRpTpxxLn1WOndAiOlk+qY8A==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/is-path-inside/download/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "http://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz",
+ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-promise/download/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/is-regex/download/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-resolvable": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-resolvable/download/is-resolvable-1.1.0.tgz",
+ "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-svg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz",
+ "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==",
+ "dev": true,
+ "requires": {
+ "html-comment-regex": "^1.1.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.2.tgz",
+ "integrity": "sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg=",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz",
+ "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "isemail": {
+ "version": "3.2.0",
+ "resolved": "http://registry.npm.taobao.org/isemail/download/isemail-3.2.0.tgz",
+ "integrity": "sha1-WTEKAhkxqfsGu7UeFVzgs/I2gyw=",
+ "dev": true,
+ "requires": {
+ "punycode": "2.x.x"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "javascript-stringify": {
+ "version": "1.6.0",
+ "resolved": "http://registry.npm.taobao.org/javascript-stringify/download/javascript-stringify-1.6.0.tgz",
+ "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=",
+ "dev": true
+ },
+ "joi": {
+ "version": "14.3.1",
+ "resolved": "http://registry.npm.taobao.org/joi/download/joi-14.3.1.tgz",
+ "integrity": "sha1-FkomLsC4VUZuDDXuoqiFrotscDw=",
+ "dev": true,
+ "requires": {
+ "hoek": "6.x.x",
+ "isemail": "3.x.x",
+ "topo": "3.x.x"
+ }
+ },
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ },
+ "js-base64": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
+ "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ=="
+ },
+ "js-levenshtein": {
+ "version": "1.1.6",
+ "resolved": "http://registry.npm.taobao.org/js-levenshtein/download/js-levenshtein-1.1.6.tgz",
+ "integrity": "sha1-xs7ljrNVA3LfjeuF+tXOZs4B1Z0=",
+ "dev": true
+ },
+ "js-message": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/js-message/download/js-message-1.0.5.tgz",
+ "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=",
+ "dev": true
+ },
+ "js-queue": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/js-queue/download/js-queue-2.0.0.tgz",
+ "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=",
+ "dev": true,
+ "requires": {
+ "easy-stack": "^1.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz",
+ "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz",
+ "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk=",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "http://registry.npm.taobao.org/json3/download/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/json5/download/json5-2.1.0.tgz",
+ "integrity": "sha1-56DGLEgoXGKNIKELhcibuAfDKFA=",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "http://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz",
+ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
+ },
+ "launch-editor": {
+ "version": "2.2.1",
+ "resolved": "http://registry.npm.taobao.org/launch-editor/download/launch-editor-2.2.1.tgz",
+ "integrity": "sha1-hxtaPuOdZoD8wm03kwtu7aidsMo=",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.3.0",
+ "shell-quote": "^1.6.1"
+ }
+ },
+ "launch-editor-middleware": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz",
+ "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==",
+ "dev": true,
+ "requires": {
+ "launch-editor": "^2.2.1"
+ }
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "load-json-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^2.2.0",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "strip-bom": "^2.0.0"
+ },
+ "dependencies": {
+ "parse-json": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
+ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
+ "requires": {
+ "error-ex": "^1.2.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ }
+ }
+ },
+ "loader-fs-cache": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/loader-fs-cache/download/loader-fs-cache-1.0.1.tgz",
+ "integrity": "sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw=",
+ "dev": true,
+ "requires": {
+ "find-cache-dir": "^0.1.1",
+ "mkdirp": "0.5.1"
+ },
+ "dependencies": {
+ "find-cache-dir": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-0.1.1.tgz",
+ "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "mkdirp": "^0.5.1",
+ "pkg-dir": "^1.0.0"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/find-up/download/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "dev": true,
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "dev": true,
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/pkg-dir/download/pkg-dir-1.0.0.tgz",
+ "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
+ "dev": true,
+ "requires": {
+ "find-up": "^1.0.0"
+ }
+ }
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "http://registry.npm.taobao.org/loader-runner/download/loader-runner-2.4.0.tgz",
+ "integrity": "sha1-7UcGa/5TTX6ExMe5mYwqdWB9k1c=",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "http://registry.npm.taobao.org/loader-utils/download/loader-utils-1.2.3.tgz",
+ "integrity": "sha1-H/XcaRHJ8KBiUxpMBLYJQGEIwsc=",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz",
+ "integrity": "sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4=",
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ }
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz",
+ "integrity": "sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ },
+ "lodash.defaultsdeep": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
+ "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
+ "dev": true
+ },
+ "lodash.kebabcase": {
+ "version": "4.1.1",
+ "resolved": "http://registry.npm.taobao.org/lodash.kebabcase/download/lodash.kebabcase-4.1.1.tgz",
+ "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=",
+ "dev": true
+ },
+ "lodash.mapvalues": {
+ "version": "4.6.0",
+ "resolved": "http://registry.npm.taobao.org/lodash.mapvalues/download/lodash.mapvalues-4.6.0.tgz",
+ "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=",
+ "dev": true
+ },
+ "lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "http://registry.npm.taobao.org/lodash.memoize/download/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
+ "dev": true
+ },
+ "lodash.tail": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
+ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ="
+ },
+ "lodash.transform": {
+ "version": "4.6.0",
+ "resolved": "http://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz",
+ "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A=",
+ "dev": true
+ },
+ "lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "http://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/log-symbols/download/log-symbols-2.2.0.tgz",
+ "integrity": "sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo=",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "http://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz",
+ "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "loud-rejection": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
+ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
+ "requires": {
+ "currently-unhandled": "^0.4.1",
+ "signal-exit": "^3.0.0"
+ }
+ },
+ "lower-case": {
+ "version": "1.1.4",
+ "resolved": "http://registry.npm.taobao.org/lower-case/download/lower-case-1.1.4.tgz",
+ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "http://registry.npm.taobao.org/lru-cache/download/lru-cache-5.1.1.tgz",
+ "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz",
+ "integrity": "sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU=",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ }
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "http://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "http://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz",
+ "integrity": "sha1-tdB7jjIW4+J81yjXL3DR5qNCAF8=",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ }
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "http://registry.npm.taobao.org/memory-fs/download/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true,
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "meow": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
+ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
+ "requires": {
+ "camelcase-keys": "^2.0.0",
+ "decamelize": "^1.1.2",
+ "loud-rejection": "^1.0.0",
+ "map-obj": "^1.0.1",
+ "minimist": "^1.1.3",
+ "normalize-package-data": "^2.3.4",
+ "object-assign": "^4.0.1",
+ "read-pkg-up": "^1.0.1",
+ "redent": "^1.0.0",
+ "trim-newlines": "^1.0.0"
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/merge-descriptors/download/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "merge-source-map": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
+ "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "merge2": {
+ "version": "1.2.3",
+ "resolved": "http://registry.npm.taobao.org/merge2/download/merge2-1.2.3.tgz",
+ "integrity": "sha1-fumdvWm7ZIFoklPwGEiKG5ArDtU=",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "http://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz",
+ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "http://registry.npm.taobao.org/miller-rabin/download/miller-rabin-4.0.1.tgz",
+ "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.2.tgz",
+ "integrity": "sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.38.0",
+ "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.38.0.tgz",
+ "integrity": "sha1-GiqrFtqesWe0nG5N8tnGjWPY4q0="
+ },
+ "mime-types": {
+ "version": "2.1.22",
+ "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.22.tgz",
+ "integrity": "sha1-/ms1WhkJJqt2mMmgVWoRGZshmb0=",
+ "requires": {
+ "mime-db": "~1.38.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz",
+ "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=",
+ "dev": true
+ },
+ "mini-css-extract-plugin": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz",
+ "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "normalize-url": "^2.0.1",
+ "schema-utils": "^1.0.0",
+ "webpack-sources": "^1.1.0"
+ },
+ "dependencies": {
+ "normalize-url": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
+ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
+ "dev": true,
+ "requires": {
+ "prepend-http": "^2.0.0",
+ "query-string": "^5.0.1",
+ "sort-keys": "^2.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/minimalistic-assert/download/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha1-LhlN4ERibUoQ5/f7wAznPoPk1cc=",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/minimalistic-crypto-utils/download/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
+ "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
+ "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/mississippi/download/mississippi-3.0.0.tgz",
+ "integrity": "sha1-6goykfl+C16HdrNj1fChLZTGcCI=",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mixin-object": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
+ "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
+ "requires": {
+ "for-in": "^0.1.3",
+ "is-extendable": "^0.1.1"
+ },
+ "dependencies": {
+ "for-in": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
+ "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE="
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz",
+ "integrity": "sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo=",
+ "dev": true
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/multicast-dns-service-types/download/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "http://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "http://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz",
+ "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "http://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "http://registry.npm.taobao.org/negotiator/download/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.0",
+ "resolved": "http://registry.npm.taobao.org/neo-async/download/neo-async-2.6.0.tgz",
+ "integrity": "sha1-udFeTXHGdikIZUtRg+04t1M0CDU="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz",
+ "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=",
+ "dev": true
+ },
+ "no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "dev": true,
+ "requires": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node-fetch": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.5.0.tgz",
+ "integrity": "sha512-YuZKluhWGJwCcUu4RlZstdAxr8bFfOVHakc1mplwHkk8J+tqM1Y5yraYvIUpeX8aY7+crCwiELJq7Vl0o0LWXw=="
+ },
+ "node-gyp": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
+ "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+ "requires": {
+ "fstream": "^1.0.0",
+ "glob": "^7.0.3",
+ "graceful-fs": "^4.1.2",
+ "mkdirp": "^0.5.0",
+ "nopt": "2 || 3",
+ "npmlog": "0 || 1 || 2 || 3 || 4",
+ "osenv": "0",
+ "request": "^2.87.0",
+ "rimraf": "2",
+ "semver": "~5.3.0",
+ "tar": "^2.0.0",
+ "which": "1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+ "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
+ },
+ "tar": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
+ "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+ "requires": {
+ "block-stream": "*",
+ "fstream": "^1.0.12",
+ "inherits": "2"
+ }
+ }
+ }
+ },
+ "node-ipc": {
+ "version": "9.1.1",
+ "resolved": "http://registry.npm.taobao.org/node-ipc/download/node-ipc-9.1.1.tgz",
+ "integrity": "sha1-TiRe1pOOZRAOWV68XcNLFujdXWk=",
+ "dev": true,
+ "requires": {
+ "event-pubsub": "4.3.0",
+ "js-message": "1.0.5",
+ "js-queue": "2.0.0"
+ }
+ },
+ "node-libs-browser": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/node-libs-browser/download/node-libs-browser-2.2.0.tgz",
+ "integrity": "sha1-xy9g2dRt4IqUDe27JfP/ovm7qnc=",
+ "dev": true,
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.0",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "node-releases": {
+ "version": "1.1.11",
+ "resolved": "http://registry.npm.taobao.org/node-releases/download/node-releases-1.1.11.tgz",
+ "integrity": "sha1-mghBpLDZK31RQe0XnnZPQq0icko=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
+ "node-sass": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.0.tgz",
+ "integrity": "sha512-AxqU+DFpk0lEz95sI6jO0hU0Rwyw7BXVEv6o9OItoXLyeygPeaSpiV4rwQb10JiTghHaa0gZeD21sz+OsQluaw==",
+ "requires": {
+ "async-foreach": "^0.1.3",
+ "chalk": "^1.1.1",
+ "cross-spawn": "^3.0.0",
+ "gaze": "^1.0.0",
+ "get-stdin": "^4.0.1",
+ "glob": "^7.0.3",
+ "in-publish": "^2.0.0",
+ "lodash": "^4.17.15",
+ "meow": "^3.7.0",
+ "mkdirp": "^0.5.1",
+ "nan": "^2.13.2",
+ "node-gyp": "^3.8.0",
+ "npmlog": "^4.0.0",
+ "request": "^2.88.0",
+ "sass-graph": "^2.2.4",
+ "stdout-stream": "^1.4.0",
+ "true-case-path": "^1.0.2"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+ "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "which": "^1.2.9"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ }
+ }
+ },
+ "nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz",
+ "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
+ "dev": true
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "http://registry.npm.taobao.org/normalize-range/download/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
+ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+ "dev": true
+ },
+ "normalize-wheel": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+ "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "http://registry.npm.taobao.org/num2fraction/download/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+ },
+ "numerify": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/numerify/-/numerify-1.2.9.tgz",
+ "integrity": "sha512-X4QzQiytV5ZN3TVLhzbtFzjTarUNnaa1pgNDFqt7u7Nqhxe7FvY2eYrGt4WYHlYXDqgtfC/n/a5nJ2y0LijV8w=="
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz",
+ "integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "http://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-hash": {
+ "version": "1.3.1",
+ "resolved": "http://registry.npm.taobao.org/object-hash/download/object-hash-1.3.1.tgz",
+ "integrity": "sha1-/eRSCYqVHLFF8Dm7fUVUSd3BJt8=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/object-keys/download/object-keys-1.1.0.tgz",
+ "integrity": "sha1-Eb0iNI3S4JagRasG9shbzDQPoDI=",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "http://registry.npm.taobao.org/object.assign/download/object.assign-4.1.0.tgz",
+ "integrity": "sha1-lovxEA15Vrs8oIbwBvhGs7xACNo=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "resolved": "http://registry.npm.taobao.org/object.getownpropertydescriptors/download/object.getownpropertydescriptors-2.0.3.tgz",
+ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.1"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
+ "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.12.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "opener": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz",
+ "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==",
+ "dev": true
+ },
+ "opn": {
+ "version": "5.5.0",
+ "resolved": "http://registry.npm.taobao.org/opn/download/opn-5.5.0.tgz",
+ "integrity": "sha1-/HFk+rVtI1kExRw7J9pnWMo7m/w=",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "http://registry.npm.taobao.org/optionator/download/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.4",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "wordwrap": "~1.0.0"
+ }
+ },
+ "ora": {
+ "version": "3.2.0",
+ "resolved": "http://registry.npm.taobao.org/ora/download/ora-3.2.0.tgz",
+ "integrity": "sha1-Z+mKfhH38KyV3qqvEbsE3j0J5IE=",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "cli-cursor": "^2.1.0",
+ "cli-spinners": "^2.0.0",
+ "log-symbols": "^2.2.0",
+ "strip-ansi": "^5.0.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "dev": true,
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/os-browserify/download/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/p-defer/download/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "resolved": "http://registry.npm.taobao.org/p-limit/download/p-limit-2.2.0.tgz",
+ "integrity": "sha1-QXyZQeYCepq8ulCS3SkE4lW1+8I=",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz",
+ "integrity": "sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "dev": true
+ },
+ "p-retry": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
+ "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
+ "dev": true,
+ "requires": {
+ "retry": "^0.12.0"
+ }
+ },
+ "p-try": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/p-try/download/p-try-2.1.0.tgz",
+ "integrity": "sha1-waDxAw6X3gGLsscYkp0q9ZRj5QU=",
+ "dev": true
+ },
+ "pako": {
+ "version": "1.0.10",
+ "resolved": "http://registry.npm.taobao.org/pako/download/pako-1.0.10.tgz",
+ "integrity": "sha1-Qyi621CGpCaqkPVBl31JVdpclzI=",
+ "dev": true
+ },
+ "parallel-transform": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/parallel-transform/download/parallel-transform-1.1.0.tgz",
+ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+ "dev": true,
+ "requires": {
+ "cyclist": "~0.2.2",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "param-case": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/param-case/download/param-case-2.1.1.tgz",
+ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "dev": true,
+ "requires": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/parent-module/download/parent-module-1.0.0.tgz",
+ "integrity": "sha1-3yUL3FOR9KCF+1idrXYfWta4ZbU=",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ },
+ "dependencies": {
+ "callsites": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/callsites/download/callsites-3.0.0.tgz",
+ "integrity": "sha1-+361abcq16RYEvk/2UMKPkELPdM=",
+ "dev": true
+ }
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.4",
+ "resolved": "http://registry.npm.taobao.org/parse-asn1/download/parse-asn1-5.1.4.tgz",
+ "integrity": "sha1-N/Zij4I/vesic7TVQENKIvPvH8w=",
+ "dev": true,
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "http://registry.npm.taobao.org/path-browserify/download/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/path-is-inside/download/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz",
+ "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "http://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/path-type/download/path-type-3.0.0.tgz",
+ "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "http://registry.npm.taobao.org/pbkdf2/download/pbkdf2-3.0.17.tgz",
+ "integrity": "sha1-l2wgZTBhexTrsyEUI597CTNuk6Y=",
+ "dev": true,
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "http://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz",
+ "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz",
+ "integrity": "sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM=",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "http://registry.npm.taobao.org/pluralize/download/pluralize-7.0.0.tgz",
+ "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=",
+ "dev": true,
+ "optional": true
+ },
+ "popper.js": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz",
+ "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA=="
+ },
+ "portal-vue": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.4.tgz",
+ "integrity": "sha512-Mr2h+RvoOOGHS7N0E3QPP+UQMt1OhSjQ7eMSGTXqkLiO0AjGEDw2x4kzmHATsZfDqQumiaYSDRzlUP2By3lvsA=="
+ },
+ "portfinder": {
+ "version": "1.0.26",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
+ "integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "debug": "^3.1.1",
+ "mkdirp": "^0.5.1"
+ },
+ "dependencies": {
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "http://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz",
+ "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-calc": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz",
+ "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==",
+ "dev": true,
+ "requires": {
+ "css-unit-converter": "^1.1.1",
+ "postcss": "^7.0.5",
+ "postcss-selector-parser": "^5.0.0-rc.4",
+ "postcss-value-parser": "^3.3.1"
+ }
+ },
+ "postcss-colormin": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz",
+ "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "color": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-convert-values": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz",
+ "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-discard-comments": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz",
+ "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-duplicates": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz",
+ "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-empty": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz",
+ "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-discard-overridden": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz",
+ "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-load-config": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
+ "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^4.0.0",
+ "import-cwd": "^2.0.0"
+ },
+ "dependencies": {
+ "cosmiconfig": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
+ "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
+ "dev": true,
+ "requires": {
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.9.0",
+ "parse-json": "^4.0.0",
+ "require-from-string": "^2.0.1"
+ }
+ }
+ }
+ },
+ "postcss-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^7.0.0",
+ "postcss-load-config": "^2.0.0",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "postcss-merge-longhand": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz",
+ "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==",
+ "dev": true,
+ "requires": {
+ "css-color-names": "0.0.4",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "stylehacks": "^4.0.0"
+ }
+ },
+ "postcss-merge-rules": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz",
+ "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "cssnano-util-same-parent": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0",
+ "vendors": "^1.0.0"
+ },
+ "dependencies": {
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "http://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-minify-font-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz",
+ "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz",
+ "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "is-color-stop": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-minify-params": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz",
+ "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "browserslist": "^4.0.0",
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "uniqs": "^2.0.0"
+ }
+ },
+ "postcss-minify-selectors": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz",
+ "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "http://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "postcss-modules-extract-imports": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz",
+ "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==",
+ "dev": true,
+ "requires": {
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-modules-local-by-default": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/postcss-modules-local-by-default/download/postcss-modules-local-by-default-1.2.0.tgz",
+ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "^0.7.0",
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-modules-scope": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/postcss-modules-scope/download/postcss-modules-scope-1.1.0.tgz",
+ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=",
+ "dev": true,
+ "requires": {
+ "css-selector-tokenizer": "^0.7.0",
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-modules-values": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npm.taobao.org/postcss-modules-values/download/postcss-modules-values-1.3.0.tgz",
+ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=",
+ "dev": true,
+ "requires": {
+ "icss-replace-symbols": "^1.1.0",
+ "postcss": "^6.0.1"
+ },
+ "dependencies": {
+ "postcss": {
+ "version": "6.0.23",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
+ "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "source-map": "^0.6.1",
+ "supports-color": "^5.4.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-normalize-charset": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz",
+ "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-normalize-display-values": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz",
+ "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-positions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz",
+ "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-repeat-style": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz",
+ "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-string": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz",
+ "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-timing-functions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz",
+ "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-unicode": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz",
+ "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-url": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz",
+ "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==",
+ "dev": true,
+ "requires": {
+ "is-absolute-url": "^2.0.0",
+ "normalize-url": "^3.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-normalize-whitespace": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz",
+ "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-ordered-values": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz",
+ "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-arguments": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-reduce-initial": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz",
+ "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "caniuse-api": "^3.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0"
+ }
+ },
+ "postcss-reduce-transforms": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz",
+ "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==",
+ "dev": true,
+ "requires": {
+ "cssnano-util-get-match": "^4.0.0",
+ "has": "^1.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0"
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
+ "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^2.0.0",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ },
+ "postcss-svgo": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz",
+ "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==",
+ "dev": true,
+ "requires": {
+ "is-svg": "^3.0.0",
+ "postcss": "^7.0.0",
+ "postcss-value-parser": "^3.0.0",
+ "svgo": "^1.0.0"
+ }
+ },
+ "postcss-unique-selectors": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz",
+ "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==",
+ "dev": true,
+ "requires": {
+ "alphanum-sort": "^1.0.0",
+ "postcss": "^7.0.0",
+ "uniqs": "^2.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
+ "prettier": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz",
+ "integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==",
+ "dev": true
+ },
+ "pretty-error": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/pretty-error/download/pretty-error-2.1.1.tgz",
+ "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=",
+ "dev": true,
+ "requires": {
+ "renderkid": "^2.0.1",
+ "utila": "~0.4"
+ }
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "http://registry.npm.taobao.org/private/download/private-0.1.8.tgz",
+ "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "http://registry.npm.taobao.org/process/download/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o="
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "http://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz",
+ "integrity": "sha1-foz42PW48jnBvGi+tOt4Vn1XLvg=",
+ "dev": true
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/promise-inflight/download/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "dev": true,
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/prr/download/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/pseudomap/download/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "psl": {
+ "version": "1.1.31",
+ "resolved": "http://registry.npm.taobao.org/psl/download/psl-1.1.31.tgz",
+ "integrity": "sha1-6aqG0BAbWxBcvpOsa3hM1UcnYYQ="
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "http://registry.npm.taobao.org/public-encrypt/download/public-encrypt-4.0.3.tgz",
+ "integrity": "sha1-T8ydd6B+SLp1J+fL4N4z0HATMeA=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz",
+ "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "http://registry.npm.taobao.org/pumpify/download/pumpify-1.5.1.tgz",
+ "integrity": "sha1-NlE74karJ1cLGjdKXOJ4v9dDcM4=",
+ "dev": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/pump/download/pump-2.0.1.tgz",
+ "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
+ "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
+ },
+ "q": {
+ "version": "1.5.1",
+ "resolved": "http://registry.npm.taobao.org/q/download/q-1.5.1.tgz",
+ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz",
+ "integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY="
+ },
+ "query-string": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
+ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
+ "dev": true,
+ "requires": {
+ "decode-uri-component": "^0.2.0",
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/querystring/download/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "http://registry.npm.taobao.org/querystring-es3/download/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+ "dev": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz",
+ "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/randomfill/download/randomfill-1.0.4.tgz",
+ "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/range-parser/download/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+ "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.0.0",
+ "http-errors": "1.6.3",
+ "iconv-lite": "0.4.23",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.23",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "read-pkg": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.0.0.tgz",
+ "integrity": "sha512-OWufaRc67oJjcgrxckW/qO9q22iYzyiONh8h+GMcnOvSHAmhV1Dr3x+gyRjP+Qxc5jKupkSfoCQLS/98rDPh9A==",
+ "dev": true,
+ "requires": {
+ "normalize-package-data": "^2.3.2",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
+ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
+ "requires": {
+ "find-up": "^1.0.0",
+ "read-pkg": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "requires": {
+ "path-exists": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
+ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
+ "requires": {
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "path-type": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
+ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
+ },
+ "read-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
+ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
+ "requires": {
+ "load-json-file": "^1.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^1.0.0"
+ }
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.6.tgz",
+ "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "http://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz",
+ "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "redent": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
+ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
+ "requires": {
+ "indent-string": "^2.1.0",
+ "strip-indent": "^1.0.1"
+ },
+ "dependencies": {
+ "strip-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
+ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
+ "requires": {
+ "get-stdin": "^4.0.1"
+ }
+ }
+ }
+ },
+ "regenerate": {
+ "version": "1.4.0",
+ "resolved": "http://registry.npm.taobao.org/regenerate/download/regenerate-1.4.0.tgz",
+ "integrity": "sha1-SoVuxLVuQHfFV1icroXnpMiGmhE=",
+ "dev": true
+ },
+ "regenerate-unicode-properties": {
+ "version": "8.0.2",
+ "resolved": "http://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.0.2.tgz",
+ "integrity": "sha1-ezj6opYlI3bTY1WM+9qQyc5wlmI=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.2",
+ "resolved": "http://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.2.tgz",
+ "integrity": "sha1-MuWcmm+5saSv8JtJMMotRHc0NEc=",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.13.4",
+ "resolved": "http://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.13.4.tgz",
+ "integrity": "sha1-GPZ2PPE4LGnDbfdsbOEizGlChPs=",
+ "dev": true,
+ "requires": {
+ "private": "^0.1.6"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz",
+ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp-tree": {
+ "version": "0.1.5",
+ "resolved": "http://registry.npm.taobao.org/regexp-tree/download/regexp-tree-0.1.5.tgz",
+ "integrity": "sha1-fNcfyhcZjQS0F279eXE/KZgAk5c=",
+ "dev": true
+ },
+ "regexpp": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/regexpp/download/regexpp-1.1.0.tgz",
+ "integrity": "sha1-DjUW3Qt5BPQT0tQZPc5GGMOmias=",
+ "dev": true,
+ "optional": true
+ },
+ "regexpu-core": {
+ "version": "4.5.4",
+ "resolved": "http://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.5.4.tgz",
+ "integrity": "sha1-CA2dAiiaqH/hZnpPUTa8mKauuq4=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.0",
+ "regenerate-unicode-properties": "^8.0.2",
+ "regjsgen": "^0.5.0",
+ "regjsparser": "^0.6.0",
+ "unicode-match-property-ecmascript": "^1.0.4",
+ "unicode-match-property-value-ecmascript": "^1.1.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.5.0",
+ "resolved": "http://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.0.tgz",
+ "integrity": "sha1-p2NNwI+JIJwgSa3aNSVxH7lyZd0=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.6.0",
+ "resolved": "http://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.0.tgz",
+ "integrity": "sha1-8eaui32iuulsmTmbhozWyTOiupw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "http://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "relateurl": {
+ "version": "0.2.7",
+ "resolved": "http://registry.npm.taobao.org/relateurl/download/relateurl-0.2.7.tgz",
+ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
+ "dev": true
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "renderkid": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz",
+ "integrity": "sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==",
+ "dev": true,
+ "requires": {
+ "css-select": "^1.1.0",
+ "dom-converter": "^0.2",
+ "htmlparser2": "^3.3.0",
+ "strip-ansi": "^3.0.0",
+ "utila": "^0.4.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "css-select": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/css-select/download/css-select-1.2.0.tgz",
+ "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+ "dev": true,
+ "requires": {
+ "boolbase": "~1.0.0",
+ "css-what": "2.1",
+ "domutils": "1.5.1",
+ "nth-check": "~1.0.1"
+ }
+ },
+ "domutils": {
+ "version": "1.5.1",
+ "resolved": "http://registry.npm.taobao.org/domutils/download/domutils-1.5.1.tgz",
+ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ },
+ "repeat-element": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz",
+ "integrity": "sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "http://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "http://registry.npm.taobao.org/request/download/request-2.88.0.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Frequest%2Fdownload%2Frequest-2.88.0.tgz",
+ "integrity": "sha1-nC/KT301tZLv5Xx/ClXoEFIST+8=",
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "request-promise-core": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.2.tgz",
+ "integrity": "sha1-M59qq6vK/bMceZ/xWHADNjAdM0Y=",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.11"
+ }
+ },
+ "request-promise-native": {
+ "version": "1.0.7",
+ "resolved": "http://registry.npm.taobao.org/request-promise-native/download/request-promise-native-1.0.7.tgz",
+ "integrity": "sha1-pJhopiS96lBp8SUdCoNuDYmqLFk=",
+ "dev": true,
+ "requires": {
+ "request-promise-core": "1.1.2",
+ "stealthy-require": "^1.1.1",
+ "tough-cookie": "^2.3.3"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/require-main-filename/download/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/require-uncached/download/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "caller-path": "^0.1.0",
+ "resolve-from": "^1.0.0"
+ }
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
+ "resolve": {
+ "version": "1.10.0",
+ "resolved": "http://registry.npm.taobao.org/resolve/download/resolve-1.10.0.tgz",
+ "integrity": "sha1-O9qur0XMB/N1ZW39LlTtCBCxAbo=",
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ }
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/resolve-from/download/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+ "dev": true,
+ "optional": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "http://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "http://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz",
+ "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=",
+ "dev": true
+ },
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
+ "dev": true
+ },
+ "rgb-regex": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz",
+ "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=",
+ "dev": true
+ },
+ "rgba-regex": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/rgba-regex/download/rgba-regex-1.0.0.tgz",
+ "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "resolved": "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.3.tgz",
+ "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/ripemd160/download/ripemd160-2.0.2.tgz",
+ "integrity": "sha1-ocGm9iR1FXe6XQeRTLyShQWFiQw=",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "http://registry.npm.taobao.org/run-async/download/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "^2.1.0"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "http://registry.npm.taobao.org/rx-lite/download/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
+ "dev": true
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "http://registry.npm.taobao.org/rx-lite-aggregates/download/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "rx-lite": "*"
+ }
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "http://registry.npm.taobao.org/rxjs/download/rxjs-6.4.0.tgz",
+ "integrity": "sha1-87sP572n+2nerAwW8XtQsLh5BQQ=",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
+ "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz",
+ "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
+ },
+ "sass-graph": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
+ "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
+ "requires": {
+ "glob": "^7.0.0",
+ "lodash": "^4.0.0",
+ "scss-tokenizer": "^0.2.3",
+ "yargs": "^7.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
+ },
+ "cliui": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+ "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
+ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
+ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "os-locale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+ "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
+ "requires": {
+ "lcid": "^1.0.0"
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
+ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ }
+ },
+ "y18n": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
+ "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
+ },
+ "yargs": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+ "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
+ "requires": {
+ "camelcase": "^3.0.0",
+ "cliui": "^3.2.0",
+ "decamelize": "^1.1.1",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^1.4.0",
+ "read-pkg-up": "^1.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^1.0.2",
+ "which-module": "^1.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^5.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
+ "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
+ "requires": {
+ "camelcase": "^3.0.0"
+ }
+ }
+ }
+ },
+ "sass-loader": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
+ "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==",
+ "requires": {
+ "clone-deep": "^2.0.1",
+ "loader-utils": "^1.0.1",
+ "lodash.tail": "^4.1.1",
+ "neo-async": "^2.5.0",
+ "pify": "^3.0.0",
+ "semver": "^5.5.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
+ }
+ }
+ },
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "http://registry.npm.taobao.org/schema-utils/download/schema-utils-0.4.7.tgz",
+ "integrity": "sha1-unT1l9K+LqiAExdG7hfQoJPGgYc=",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "scss-tokenizer": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
+ "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
+ "requires": {
+ "js-base64": "^2.1.8",
+ "source-map": "^0.4.2"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/select-hose/download/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.6.0",
+ "resolved": "http://registry.npm.taobao.org/semver/download/semver-5.6.0.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.6.0.tgz",
+ "integrity": "sha1-fnQlb7qknHWqfHogXMInmcrIAAQ="
+ },
+ "send": {
+ "version": "0.16.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
+ "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.6.2",
+ "mime": "1.4.1",
+ "ms": "2.0.0",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.0",
+ "statuses": "~1.4.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "mime": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
+ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.6.1",
+ "resolved": "http://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-1.6.1.tgz",
+ "integrity": "sha1-TR9pfsSUKahHym9EKip1USbE2Hk=",
+ "dev": true
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "http://registry.npm.taobao.org/serve-index/download/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
+ "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.2",
+ "send": "0.16.2"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/setimmediate/download/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "http://registry.npm.taobao.org/sha.js/download/sha.js-2.4.11.tgz",
+ "integrity": "sha1-N6XPC4HsvGlD3hCbopYNGyZYSuc=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
+ "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
+ "requires": {
+ "is-extendable": "^0.1.1",
+ "kind-of": "^5.0.0",
+ "mixin-object": "^2.0.1"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "http://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "shell-quote": {
+ "version": "1.6.1",
+ "resolved": "http://registry.npm.taobao.org/shell-quote/download/shell-quote-1.6.1.tgz",
+ "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=",
+ "dev": true,
+ "requires": {
+ "array-filter": "~0.0.0",
+ "array-map": "~0.0.0",
+ "array-reduce": "~0.0.0",
+ "jsonify": "~0.0.0"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "http://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "http://registry.npm.taobao.org/simple-swizzle/download/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.3.1"
+ },
+ "dependencies": {
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "dev": true
+ }
+ }
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/slash/download/slash-2.0.0.tgz",
+ "integrity": "sha1-3lUoUaF1nfOo8gZTVEL17E3eq0Q=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/slice-ansi/download/slice-ansi-1.0.0.tgz",
+ "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0"
+ }
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "http://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz",
+ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz",
+ "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz",
+ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "http://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "sockjs": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.0.1"
+ }
+ },
+ "sort-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+ "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^1.0.0"
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/source-list-map/download/source-list-map-2.0.1.tgz",
+ "integrity": "sha1-OZO9hzv8SEecyp6jpUeDXHwVSzQ=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "http://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "http://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
+ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
+ "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA=="
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz",
+ "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA=="
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+ "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "http://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz",
+ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz",
+ "integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=",
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "http://registry.npm.taobao.org/ssri/download/ssri-6.0.1.tgz",
+ "integrity": "sha1-KjxBso3UW2K2Nnbst0ABJlrp7dg=",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "stable": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
+ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
+ "dev": true
+ },
+ "stackframe": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz",
+ "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==",
+ "dev": true
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "http://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "http://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+ "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+ "dev": true
+ },
+ "stdout-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
+ "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
+ "requires": {
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "stealthy-require": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz",
+ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "http://registry.npm.taobao.org/stream-browserify/download/stream-browserify-2.0.2.tgz",
+ "integrity": "sha1-h1IdOKRKp+6RzhzSpH3wy0ndZgs=",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "http://registry.npm.taobao.org/stream-each/download/stream-each-1.2.3.tgz",
+ "integrity": "sha1-6+J6DDibBPvMIzZClS4Qcxr6m64=",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "http://registry.npm.taobao.org/stream-http/download/stream-http-2.8.3.tgz",
+ "integrity": "sha1-stJCRpKIpaJ+xP6JM6z2I95lFPw=",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz",
+ "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string.prototype.padend": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/string.prototype.padend/download/string.prototype.padend-3.0.0.tgz",
+ "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.4.3",
+ "function-bind": "^1.0.2"
+ }
+ },
+ "string.prototype.padstart": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/string.prototype.padstart/download/string.prototype.padstart-3.0.0.tgz",
+ "integrity": "sha1-W8+tOfRkm7LQMSkuGbzwtRDUskI=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.4.3",
+ "function-bind": "^1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz",
+ "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz",
+ "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ },
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/strip-indent/download/strip-indent-2.0.0.tgz",
+ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "stylehacks": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
+ "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.0.0",
+ "postcss": "^7.0.0",
+ "postcss-selector-parser": "^3.0.0"
+ },
+ "dependencies": {
+ "postcss-selector-parser": {
+ "version": "3.1.1",
+ "resolved": "http://registry.npm.taobao.org/postcss-selector-parser/download/postcss-selector-parser-3.1.1.tgz",
+ "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=",
+ "dev": true,
+ "requires": {
+ "dot-prop": "^4.1.1",
+ "indexes-of": "^1.0.1",
+ "uniq": "^1.0.1"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "http://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz",
+ "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "svg-tags": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz",
+ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+ "dev": true
+ },
+ "svgo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
+ "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.1",
+ "coa": "^2.0.2",
+ "css-select": "^2.0.0",
+ "css-select-base-adapter": "^0.1.1",
+ "css-tree": "1.0.0-alpha.37",
+ "csso": "^4.0.2",
+ "js-yaml": "^3.13.1",
+ "mkdirp": "~0.5.1",
+ "object.values": "^1.1.0",
+ "sax": "~1.2.4",
+ "stable": "^0.1.8",
+ "unquote": "~1.1.1",
+ "util.promisify": "~1.0.0"
+ },
+ "dependencies": {
+ "css-tree": {
+ "version": "1.0.0-alpha.37",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
+ "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "2.0.4",
+ "source-map": "^0.6.1"
+ }
+ },
+ "csso": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz",
+ "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==",
+ "dev": true,
+ "requires": {
+ "css-tree": "1.0.0-alpha.39"
+ },
+ "dependencies": {
+ "css-tree": {
+ "version": "1.0.0-alpha.39",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz",
+ "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==",
+ "dev": true,
+ "requires": {
+ "mdn-data": "2.0.6",
+ "source-map": "^0.6.1"
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz",
+ "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==",
+ "dev": true
+ }
+ }
+ },
+ "mdn-data": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
+ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "http://registry.npm.taobao.org/table/download/table-4.0.2.tgz",
+ "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ajv": "^5.2.3",
+ "ajv-keywords": "^2.1.0",
+ "chalk": "^2.1.0",
+ "lodash": "^4.17.4",
+ "slice-ansi": "1.0.0",
+ "string-width": "^2.1.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "dev": true,
+ "optional": true
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true,
+ "optional": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "tapable": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/tapable/download/tapable-1.1.1.tgz",
+ "integrity": "sha1-TSl5I8WnKkI2DeKrUtrfquwAAY4=",
+ "dev": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
+ "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
+ "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
+ "dev": true,
+ "requires": {
+ "cacache": "^12.0.2",
+ "find-cache-dir": "^2.1.0",
+ "is-wsl": "^1.1.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^2.1.2",
+ "source-map": "^0.6.1",
+ "terser": "^4.1.2",
+ "webpack-sources": "^1.4.0",
+ "worker-farm": "^1.7.0"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "cacache": {
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
+ "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "serialize-javascript": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
+ "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+ "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "terser": {
+ "version": "4.6.13",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz",
+ "integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.12"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ }
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "dev": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "http://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "thread-loader": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-2.1.2.tgz",
+ "integrity": "sha512-7xpuc9Ifg6WU+QYw/8uUqNdRwMD+N5gjwHKMqETrs96Qn+7BHwECpt2Brzr4HFlf4IAkZsayNhmGdbkBsTJ//w==",
+ "dev": true,
+ "requires": {
+ "loader-runner": "^2.3.1",
+ "loader-utils": "^1.1.0",
+ "neo-async": "^2.6.0"
+ }
+ },
+ "throttle-debounce": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+ "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "http://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz",
+ "integrity": "sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0=",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
+ "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.10",
+ "resolved": "http://registry.npm.taobao.org/timers-browserify/download/timers-browserify-2.0.10.tgz",
+ "integrity": "sha1-HSjj0qrfHVpZlsTp+VYBzQU0gK4=",
+ "dev": true,
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "timsort": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz",
+ "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
+ "dev": true
+ },
+ "tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "http://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz",
+ "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/to-arraybuffer/download/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "http://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "http://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz",
+ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "http://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "dev": true
+ },
+ "topo": {
+ "version": "3.0.3",
+ "resolved": "http://registry.npm.taobao.org/topo/download/topo-3.0.3.tgz",
+ "integrity": "sha1-1aZ/suaTB+vusIQC7Coqb1962Vw=",
+ "dev": true,
+ "requires": {
+ "hoek": "6.x.x"
+ }
+ },
+ "toposort": {
+ "version": "1.0.7",
+ "resolved": "http://registry.npm.taobao.org/toposort/download/toposort-1.0.7.tgz",
+ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=",
+ "dev": true
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.4.3.tgz",
+ "integrity": "sha1-U/Nto/R3g7CSWvoG/587FlKA94E=",
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ }
+ }
+ },
+ "trim-newlines": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
+ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/trim-right/download/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "true-case-path": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
+ "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
+ "requires": {
+ "glob": "^7.1.2"
+ }
+ },
+ "tryer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
+ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
+ "dev": true
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "http://registry.npm.taobao.org/tslib/download/tslib-1.9.3.tgz?cache=0&other_urls=http%3A%2F%2Fregistry.npm.taobao.org%2Ftslib%2Fdownload%2Ftslib-1.9.3.tgz",
+ "integrity": "sha1-1+TdeSRdhUKMTX5IIqeZF5VMooY=",
+ "dev": true
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "http://registry.npm.taobao.org/tty-browserify/download/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "http://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ },
+ "type-is": {
+ "version": "1.6.16",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+ "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.18"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "http://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "uglify-js": {
+ "version": "3.4.10",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
+ "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.19.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
+ "integrity": "sha1-JhmADEyCWADv3YNDr33Zkzy+KBg=",
+ "dev": true
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "http://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz",
+ "integrity": "sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw=",
+ "dev": true,
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^1.0.4",
+ "unicode-property-aliases-ecmascript": "^1.0.4"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "1.1.0",
+ "resolved": "http://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.1.0.tgz",
+ "integrity": "sha1-W0tCbgjROoA2Xg1lesemwexGonc=",
+ "dev": true
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "1.0.5",
+ "resolved": "http://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.0.5.tgz",
+ "integrity": "sha1-qcxsx85joKMCP8meNBuUQx1AWlc=",
+ "dev": true
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ }
+ },
+ "uniq": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/uniq/download/uniq-1.0.1.tgz",
+ "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
+ "dev": true
+ },
+ "uniqs": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/uniqs/download/uniqs-2.0.0.tgz",
+ "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=",
+ "dev": true
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/unique-filename/download/unique-filename-1.1.1.tgz",
+ "integrity": "sha1-HWl2k2mtoFgxA6HmrodoG1ZXMjA=",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.1",
+ "resolved": "http://registry.npm.taobao.org/unique-slug/download/unique-slug-2.0.1.tgz",
+ "integrity": "sha1-Xp7cbRzo+yZNsYpQfvm9hURFHKY=",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "unquote": {
+ "version": "1.1.1",
+ "resolved": "http://registry.npm.taobao.org/unquote/download/unquote-1.1.1.tgz",
+ "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "http://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "http://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "http://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/upath/download/upath-1.1.2.tgz",
+ "integrity": "sha1-PbZYYA7a7sy+bbXmhNZ+6MKs0Gg=",
+ "dev": true
+ },
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "http://registry.npm.taobao.org/upper-case/download/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "http://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz",
+ "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "http://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "http://registry.npm.taobao.org/url/download/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "dev": true,
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+ "dev": true
+ }
+ }
+ },
+ "url-loader": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz",
+ "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "mime": "^2.0.3",
+ "schema-utils": "^1.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
+ "url-parse": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.6.tgz",
+ "integrity": "sha512-/B8AD9iQ01seoXmXf9z/MjLZQIdOoYl/+gvsQF6+mpnxaTfG9P7srYaiqaDMyKkR36XMXfhqSHss5MyFAO8lew==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "http://registry.npm.taobao.org/use/download/use-3.1.1.tgz",
+ "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=",
+ "dev": true
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "http://registry.npm.taobao.org/util/download/util-0.11.1.tgz",
+ "integrity": "sha1-MjZzNyDsZLsn9uJvQhqqLhtYjWE=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "util.promisify": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/util.promisify/download/util.promisify-1.0.0.tgz",
+ "integrity": "sha1-RA9xZaRZyaFtwUXrjnLzVocJcDA=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "utila": {
+ "version": "0.4.0",
+ "resolved": "http://registry.npm.taobao.org/utila/download/utila-0.4.0.tgz",
+ "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
+ "dev": true
+ },
+ "utils-lite": {
+ "version": "0.1.10",
+ "resolved": "https://registry.npmjs.org/utils-lite/-/utils-lite-0.1.10.tgz",
+ "integrity": "sha512-jlHvdtI8MyWURF/3u+ufIjf1Cs5WjN6WZl9qO8dEkZsVjaI7X5YMUhaCFzkvB69ljt6fo4Dd7V/Oj2NJOFDFOQ=="
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.3.2.tgz",
+ "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE="
+ },
+ "v-charts": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/v-charts/-/v-charts-1.19.0.tgz",
+ "integrity": "sha512-vm2HBUmxAsXK0ivwce9LytcpqrItDA5JSPLYVxZXtiuoyhcn80XX1/3dPJd/1GqG1OYv3jfBo1s9ra4q8GowqA==",
+ "requires": {
+ "echarts-amap": "1.0.0-rc.6",
+ "echarts-liquidfill": "^2.0.2",
+ "echarts-wordcloud": "^1.1.3",
+ "numerify": "1.2.9",
+ "utils-lite": "0.1.10"
+ }
+ },
+ "v-contextmenu": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/v-contextmenu/-/v-contextmenu-2.8.0.tgz",
+ "integrity": "sha512-Cj5iYDI4R4cwjLKF0vSJChVrQNWUjgV780Fc0gPwZNUxa3ZsRh94whhSOUdGVEURQaapNQ/4RXTqrKB310eGuw==",
+ "requires": {
+ "vue": "^2.5.16"
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "http://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "vee-validate": {
+ "version": "2.2.15",
+ "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-2.2.15.tgz",
+ "integrity": "sha512-4TOsI8XwVkKVLkg8Nhmy+jyoJrR6XcTRDyxBarzcCvYzU61zamipS1WsB6FlDze8eJQpgglS4NXAS6o4NDPs1g=="
+ },
+ "vendors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz",
+ "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "http://registry.npm.taobao.org/vm-browserify/download/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "dev": true,
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "vue": {
+ "version": "2.6.10",
+ "resolved": "http://registry.npm.taobao.org/vue/download/vue-2.6.10.tgz",
+ "integrity": "sha1-pysaQqTYKnIepDjRtr9V5mGVxjc="
+ },
+ "vue-ads-form-builder": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/vue-ads-form-builder/-/vue-ads-form-builder-0.1.15.tgz",
+ "integrity": "sha512-7J3itnT+MHqODyO39JkGetREA1YlnNVHYj6KGlT9uGMnNr1H7NmTStasoZ1bpHU7AJ5Uyyp7tuWZl105H7DEPw==",
+ "requires": {
+ "@fortawesome/fontawesome-free": "^5.7.2",
+ "vee-validate": "^2.1.7",
+ "vue": "^2.6.6",
+ "vue-perfect-scrollbar": "^0.1.0"
+ }
+ },
+ "vue-ads-pagination": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/vue-ads-pagination/-/vue-ads-pagination-2.1.7.tgz",
+ "integrity": "sha512-uvWHvHjG3KhdiVeLm4v5DP4K3+MlczizSLCuILNHnWghvt6q6og3L7k8fGuyXFyqMOBftEdV90WU6wRcNCqwtA==",
+ "requires": {
+ "@fortawesome/fontawesome-free": "^5.11.2",
+ "vue": "^2.6.10"
+ }
+ },
+ "vue-ads-table-tree": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/vue-ads-table-tree/-/vue-ads-table-tree-2.4.2.tgz",
+ "integrity": "sha512-PBWA1fFw/AdislGkb+zSsvdPQaLrabxymrJq44wsuKIcQUeIWA6bGS/0239XbpsWkuIt6Gtj6yIoSypj5A3qAw==",
+ "requires": {
+ "@fortawesome/fontawesome-free": "^5.11.2",
+ "vue": "^2.6.10",
+ "vue-ads-form-builder": "^0.1.15",
+ "vue-ads-pagination": "^2.1.7",
+ "vue-json-excel": "^0.2.98"
+ }
+ },
+ "vue-chartjs": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-3.4.2.tgz",
+ "integrity": "sha512-EhoXUJ17+9isMLhJpOliS++xE5z5FM8iAVytIqnKofByVMr8AISRL/SCy3zvWbvzhjgQPStd9y6adMF5bnWQdg=="
+ },
+ "vue-click-outside": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/vue-click-outside/-/vue-click-outside-1.0.7.tgz",
+ "integrity": "sha1-zdKxYF48SUR4TheU6uShKg9wC9Y="
+ },
+ "vue-clipboard2": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/vue-clipboard2/-/vue-clipboard2-0.3.0.tgz",
+ "integrity": "sha512-6/Y9NJErWb4LNBLMgsJSdKb7KpF6/jqXagvKlYut6VQzQsNj6515FpwH0r5hhmeJMqaPzf1kxAw8L8Qvw/QBJQ==",
+ "requires": {
+ "clipboard": "^2.0.0"
+ }
+ },
+ "vue-cookies": {
+ "version": "1.5.13",
+ "resolved": "https://registry.npmjs.org/vue-cookies/-/vue-cookies-1.5.13.tgz",
+ "integrity": "sha512-8pjpXnvbNWx1Lft0t3MJnW+ylv0Wa2Tb6Ch617u/pQah3+SfXUZZdkh3EL3bSpe/Sw2Wdw3+DhycgQsKANSxXg=="
+ },
+ "vue-eslint-parser": {
+ "version": "2.0.3",
+ "resolved": "http://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-2.0.3.tgz",
+ "integrity": "sha1-wmjJbG2Uz+PZOKX3WTlZsMozYNE=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^3.1.0",
+ "eslint-scope": "^3.7.1",
+ "eslint-visitor-keys": "^1.0.0",
+ "espree": "^3.5.2",
+ "esquery": "^1.0.0",
+ "lodash": "^4.17.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "http://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz",
+ "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.3",
+ "resolved": "http://registry.npm.taobao.org/eslint-scope/download/eslint-scope-3.7.3.tgz",
+ "integrity": "sha1-u1ByANPRf2AkdjYWC0gmKEsQhTU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ }
+ }
+ },
+ "vue-functional-data-merge": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz",
+ "integrity": "sha512-pvLc+H+x2prwBj/uSEIITyxjz/7ZUVVK8uYbrYMmhDvMXnzh9OvQvVEwcOSBQjsubd4Eq41/CSJaWzy4hemMNQ=="
+ },
+ "vue-hot-reload-api": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz",
+ "integrity": "sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g==",
+ "dev": true
+ },
+ "vue-i18n": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.9.0.tgz",
+ "integrity": "sha512-8wr/D9yU8CLC8ne9stdQn/N58E7GRSUSO75bCucj2AIFTDyjGfoze5RxFvh2w3e7yxgnz5x+ooOIcoX59PHguQ=="
+ },
+ "vue-json-excel": {
+ "version": "0.2.98",
+ "resolved": "https://registry.npmjs.org/vue-json-excel/-/vue-json-excel-0.2.98.tgz",
+ "integrity": "sha512-hPA3/cOe5nGbEZiJyfpdBIdqBExxF6EhMhpX6vC654PYbTVzdzp7O9ZsC1AgqbgRDR8VjzAaPaEeHg2vGS88FQ==",
+ "requires": {
+ "downloadjs": "^1.4.7"
+ }
+ },
+ "vue-loader": {
+ "version": "15.7.0",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.0.tgz",
+ "integrity": "sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA==",
+ "dev": true,
+ "requires": {
+ "@vue/component-compiler-utils": "^2.5.1",
+ "hash-sum": "^1.0.2",
+ "loader-utils": "^1.1.0",
+ "vue-hot-reload-api": "^2.3.0",
+ "vue-style-loader": "^4.1.0"
+ }
+ },
+ "vue-perfect-scrollbar": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/vue-perfect-scrollbar/-/vue-perfect-scrollbar-0.1.0.tgz",
+ "integrity": "sha512-l/ZEidPDFplXeDtxs+gO3D8efhwqyIEcUtfvfRujCQemcn39ghpSNoizWWZYI6Ro0iz3yP+w7LqNxEBjE+T1qQ=="
+ },
+ "vue-router": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz",
+ "integrity": "sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg=="
+ },
+ "vue-style-loader": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
+ "integrity": "sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==",
+ "dev": true,
+ "requires": {
+ "hash-sum": "^1.0.2",
+ "loader-utils": "^1.0.2"
+ }
+ },
+ "vue-template-compiler": {
+ "version": "2.6.10",
+ "resolved": "http://registry.npm.taobao.org/vue-template-compiler/download/vue-template-compiler-2.6.10.tgz",
+ "integrity": "sha1-MjtPNJXwT6o1AzN6gvXWUHeZycw=",
+ "dev": true,
+ "requires": {
+ "de-indent": "^1.0.2",
+ "he": "^1.1.0"
+ }
+ },
+ "vue-template-es2015-compiler": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
+ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
+ "dev": true
+ },
+ "watchpack": {
+ "version": "1.6.0",
+ "resolved": "http://registry.npm.taobao.org/watchpack/download/watchpack-1.6.0.tgz",
+ "integrity": "sha1-S8EsLr6KonenHx0/FNaFx7RGzQA=",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "wcwidth": {
+ "version": "1.0.1",
+ "resolved": "http://registry.npm.taobao.org/wcwidth/download/wcwidth-1.0.1.tgz",
+ "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
+ "dev": true,
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "webpack": {
+ "version": "4.28.4",
+ "resolved": "http://registry.npm.taobao.org/webpack/download/webpack-4.28.4.tgz",
+ "integrity": "sha1-HdrmyJiH1++3Uq3ww80yubB+rNA=",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.7.11",
+ "@webassemblyjs/helper-module-context": "1.7.11",
+ "@webassemblyjs/wasm-edit": "1.7.11",
+ "@webassemblyjs/wasm-parser": "1.7.11",
+ "acorn": "^5.6.2",
+ "acorn-dynamic-import": "^3.0.0",
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0",
+ "chrome-trace-event": "^1.0.0",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.3.0",
+ "loader-utils": "^1.1.0",
+ "memory-fs": "~0.4.1",
+ "micromatch": "^3.1.8",
+ "mkdirp": "~0.5.0",
+ "neo-async": "^2.5.0",
+ "node-libs-browser": "^2.0.0",
+ "schema-utils": "^0.4.4",
+ "tapable": "^1.1.0",
+ "terser-webpack-plugin": "^1.1.0",
+ "watchpack": "^1.5.0",
+ "webpack-sources": "^1.3.0"
+ }
+ },
+ "webpack-bundle-analyzer": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.7.0.tgz",
+ "integrity": "sha512-mETdjZ30a3Yf+NTB/wqTgACK7rAYQl5uxKK0WVTNmF0sM3Uv8s3R58YZMW7Rhu0Lk2Rmuhdj5dcH5Q76zCDVdA==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.1.1",
+ "acorn-walk": "^7.1.1",
+ "bfj": "^6.1.1",
+ "chalk": "^2.4.1",
+ "commander": "^2.18.0",
+ "ejs": "^2.6.1",
+ "express": "^4.16.3",
+ "filesize": "^3.6.1",
+ "gzip-size": "^5.0.0",
+ "lodash": "^4.17.15",
+ "mkdirp": "^0.5.1",
+ "opener": "^1.5.1",
+ "ws": "^6.0.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
+ "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+ "dev": true
+ },
+ "acorn-walk": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
+ "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-chain": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz",
+ "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==",
+ "dev": true,
+ "requires": {
+ "deepmerge": "^1.5.2",
+ "javascript-stringify": "^1.6.0"
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.10.3",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz",
+ "integrity": "sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.1.8",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^1.6.0",
+ "debug": "^4.1.1",
+ "del": "^4.1.1",
+ "express": "^4.17.1",
+ "html-entities": "^1.2.1",
+ "http-proxy-middleware": "0.19.1",
+ "import-local": "^2.0.0",
+ "internal-ip": "^4.3.0",
+ "ip": "^1.1.5",
+ "is-absolute-url": "^3.0.3",
+ "killable": "^1.0.1",
+ "loglevel": "^1.6.6",
+ "opn": "^5.5.0",
+ "p-retry": "^3.0.1",
+ "portfinder": "^1.0.25",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.10.7",
+ "semver": "^6.3.0",
+ "serve-index": "^1.9.1",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.4.0",
+ "spdy": "^4.0.1",
+ "strip-ansi": "^3.0.1",
+ "supports-color": "^6.1.0",
+ "url": "^0.11.0",
+ "webpack-dev-middleware": "^3.7.2",
+ "webpack-log": "^2.0.0",
+ "ws": "^6.2.1",
+ "yargs": "12.0.5"
+ },
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "dev": true
+ },
+ "del": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
+ "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "globby": "^6.1.0",
+ "is-path-cwd": "^2.0.0",
+ "is-path-in-cwd": "^2.0.0",
+ "p-map": "^2.0.0",
+ "pify": "^4.0.1",
+ "rimraf": "^2.6.3"
+ }
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "is-absolute-url": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
+ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==",
+ "dev": true
+ },
+ "loglevel": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
+ "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==",
+ "dev": true
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.44.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+ "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.27",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+ "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.44.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "dev": true
+ },
+ "node-forge": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
+ "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "selfsigned": {
+ "version": "1.10.7",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
+ "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.9.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+ "dev": true
+ },
+ "sockjs-client": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz",
+ "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz",
+ "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "^0.4.1",
+ "mime": "^2.4.4",
+ "mkdirp": "^0.5.1",
+ "range-parser": "^1.2.1",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ }
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "webpack-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz",
+ "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.5"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.3.0",
+ "resolved": "http://registry.npm.taobao.org/webpack-sources/download/webpack-sources-1.3.0.tgz",
+ "integrity": "sha1-KijcufH0X+lg2PFJMlK17mUw+oU=",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz",
+ "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
+ "dev": true
+ }
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.0",
+ "resolved": "http://registry.npm.taobao.org/websocket-driver/download/websocket-driver-0.7.0.tgz",
+ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.4.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "http://registry.npm.taobao.org/which/download/which-1.3.1.tgz",
+ "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "http://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "http://registry.npm.taobao.org/write/download/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "mkdirp": "^0.5.1"
+ }
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "http://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz",
+ "integrity": "sha1-le+U+F7MgdAHwmThkKEg8KPIVms=",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-3.0.3.tgz",
+ "integrity": "sha1-tLBJ4xS+VF486AIjbWzSLNkcPek="
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ }
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yorkie": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yorkie/-/yorkie-2.0.0.tgz",
+ "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==",
+ "dev": true,
+ "requires": {
+ "execa": "^0.8.0",
+ "is-ci": "^1.0.10",
+ "normalize-path": "^1.0.0",
+ "strip-indent": "^2.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "http://registry.npm.taobao.org/cross-spawn/download/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "0.8.0",
+ "resolved": "http://registry.npm.taobao.org/execa/download/execa-0.8.0.tgz",
+ "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "3.0.0",
+ "resolved": "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz",
+ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "normalize-path": {
+ "version": "1.0.0",
+ "resolved": "http://registry.npm.taobao.org/normalize-path/download/normalize-path-1.0.0.tgz",
+ "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=",
+ "dev": true
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "http://registry.npm.taobao.org/yallist/download/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "zrender": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/zrender/-/zrender-4.2.0.tgz",
+ "integrity": "sha512-YJ9hxt5uFincYYU3KK31+Ce+B6PJmYYK0Q9fQ6jOUAoC/VHbe4kCKAPkxKeT7jGTxrK5wYu18R0TLGqj2zbEOA=="
+ }
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..aa892a1
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "Jifa",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "serve": "vue-cli-service serve",
+ "dev-build": "vue-cli-service build --mode development --dest build",
+ "prod-build": "vue-cli-service build --mode production --dest build",
+ "build": "vue-cli-service build --mode production --dest build",
+ "lint": "vue-cli-service lint"
+ },
+ "dependencies": {
+ "axios": "^0.18.1",
+ "bootstrap-vue": "^2.0.0-rc.19",
+ "chart.js": "^2.8.0",
+ "echarts": "^4.6.0",
+ "element-ui": "^2.13.1",
+ "font-awesome": "^4.7.0",
+ "jquery": "^3.4.1",
+ "node-sass": "^4.14.0",
+ "popper.js": "^1.15.0",
+ "sass-loader": "^7.1.0",
+ "tar": "^4.4.8",
+ "v-charts": "^1.9.0",
+ "v-contextmenu": "^2.8.0",
+ "vue": "^2.6.10",
+ "vue-ads-table-tree": "^2.4.2",
+ "vue-chartjs": "^3.4.2",
+ "vue-click-outside": "^1.0.7",
+ "vue-clipboard2": "^0.3.0",
+ "vue-cookies": "^1.5.13",
+ "vue-i18n": "^8.9.0",
+ "vue-router": "^3.0.2"
+ },
+ "devDependencies": {
+ "@vue/cli-plugin-babel": "^3.5.0",
+ "@vue/cli-plugin-eslint": "^3.5.0",
+ "@vue/cli-service": "^3.6.0",
+ "babel-eslint": "^10.0.1",
+ "eslint": "^5.8.0",
+ "eslint-plugin-vue": "^5.0.0",
+ "vue-template-compiler": "^2.5.21"
+ },
+ "eslintConfig": {
+ "root": true,
+ "env": {
+ "node": true
+ },
+ "extends": [
+ "plugin:vue/essential",
+ "eslint:recommended"
+ ],
+ "rules": {},
+ "parserOptions": {
+ "parser": "babel-eslint"
+ }
+ },
+ "postcss": {
+ "plugins": {
+ "autoprefixer": {}
+ }
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions",
+ "not ie <= 8"
+ ]
+}
diff --git a/frontend/public/eclipse_incubation_vertical_png.png b/frontend/public/eclipse_incubation_vertical_png.png
new file mode 100644
index 0000000..51c6273
--- /dev/null
+++ b/frontend/public/eclipse_incubation_vertical_png.png
Binary files differ
diff --git a/frontend/public/index.html b/frontend/public/index.html
new file mode 100644
index 0000000..bbb1b31
--- /dev/null
+++ b/frontend/public/index.html
@@ -0,0 +1,30 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <link rel="icon" href="<%= BASE_URL %>eclipse_incubation_vertical_png.png">
+ <title data-react-helmet="true">Jifa</title>
+ <meta name="description" property="og:description" content="Jifa"/>
+</head>
+<body>
+<noscript>
+ <strong>We're sorry but Jifa doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+</noscript>
+<div id="app"></div>
+<!-- built files will be auto injected -->
+</body>
+</html>
diff --git a/frontend/src/Jifa.css b/frontend/src/Jifa.css
new file mode 100644
index 0000000..7cece98
--- /dev/null
+++ b/frontend/src/Jifa.css
@@ -0,0 +1,35 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+:focus {
+ outline: none;
+}
+
+button:focus {
+ outline: none;
+}
+
+a:hover {
+ text-decoration: none;
+}
+
+a:not([href]):not([tabindex]) {
+ color: #606266;
+}
+
+a:not([href]):not([tabindex]):hover {
+ color: #409EFF;
+}
+
+a:not([href]):not([tabindex]):focus {
+ color: #409EFF;
+}
\ No newline at end of file
diff --git a/frontend/src/Jifa.js b/frontend/src/Jifa.js
new file mode 100644
index 0000000..634a3b9
--- /dev/null
+++ b/frontend/src/Jifa.js
@@ -0,0 +1,21 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export default class JifaGlobal {
+ static prod() {
+ return process.env.NODE_ENV === 'production'
+ }
+
+ static dev() {
+ return process.env.NODE_ENV === 'development'
+ }
+}
diff --git a/frontend/src/Jifa.vue b/frontend/src/Jifa.vue
new file mode 100644
index 0000000..c6db415
--- /dev/null
+++ b/frontend/src/Jifa.vue
@@ -0,0 +1,25 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <router-view/>
+</template>
+
+<script>
+ export default {}
+</script>
+
+<style>
+ html, body {
+ height: 100%;
+ }
+</style>
\ No newline at end of file
diff --git a/frontend/src/assets/eclipse_incubation_vertical_svg.svg b/frontend/src/assets/eclipse_incubation_vertical_svg.svg
new file mode 100644
index 0000000..394e6a2
--- /dev/null
+++ b/frontend/src/assets/eclipse_incubation_vertical_svg.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 210.79 276.54" style="enable-background:new 0 0 210.79 276.54;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#3D3935;}
+ .st1{fill:#F78D2C;}
+</style>
+<g>
+ <path class="st0" d="M43.75,237.34h1.17v15.69h-1.17V237.34z"/>
+ <path class="st0" d="M48.62,237.34h1.1l10.83,13.65v-13.65h1.12v15.69h-0.87l-11.05-13.94v13.94h-1.12V237.34z"/>
+ <path class="st0" d="M64.86,245.23v-0.04c0-4.44,3.32-8.11,7.85-8.11c2.8,0,4.48,1.03,6.1,2.51l-0.83,0.85
+ c-1.37-1.32-2.94-2.31-5.29-2.31c-3.77,0-6.61,3.07-6.61,7.02v0.04c0,3.97,2.89,7.06,6.63,7.06c2.26,0,3.81-0.88,5.4-2.44
+ l0.78,0.76c-1.66,1.64-3.45,2.73-6.23,2.73C68.18,253.3,64.86,249.74,64.86,245.23z"/>
+ <path class="st0" d="M81.4,246.51v-9.17h1.17v9.06c0,3.7,2,5.83,5.31,5.83c3.18,0,5.22-1.93,5.22-5.72v-9.17h1.17v9.03
+ c0,4.51-2.62,6.9-6.43,6.9C84.07,253.28,81.4,250.9,81.4,246.51z"/>
+ <path class="st0" d="M97.02,237.34h6.48c1.77,0,3.21,0.52,4.08,1.39c0.65,0.65,1.01,1.48,1.01,2.47v0.04
+ c0,2.13-1.39,3.21-2.67,3.72c1.88,0.49,3.54,1.57,3.54,3.74v0.04c0,2.62-2.24,4.28-5.63,4.28h-6.81V237.34z M107.4,241.31
+ c0-1.73-1.41-2.89-3.92-2.89h-5.29v6.16h5.18c2.35,0,4.03-1.14,4.03-3.23V241.31z M103.5,245.66h-5.31v6.3h5.69
+ c2.69,0,4.39-1.23,4.39-3.21v-0.04C108.28,246.78,106.6,245.66,103.5,245.66z"/>
+ <path class="st0" d="M119.28,237.23h1.12l7.31,15.8h-1.28l-1.99-4.39h-9.26l-1.99,4.39h-1.21L119.28,237.23z M123.94,247.59
+ l-4.12-9.08l-4.15,9.08H123.94z"/>
+ <path class="st0" d="M134.05,238.42h-5.47v-1.08h12.1v1.08h-5.47v14.61h-1.17V238.42z"/>
+ <path class="st0" d="M144.29,237.34h1.17v15.69h-1.17V237.34z"/>
+ <path class="st0" d="M148.91,245.23v-0.04c0-4.28,3.16-8.11,7.91-8.11s7.87,3.79,7.87,8.07v0.04c0,4.28-3.16,8.11-7.91,8.11
+ S148.91,249.51,148.91,245.23z M163.48,245.23v-0.04c0-3.88-2.82-7.06-6.7-7.06s-6.66,3.14-6.66,7.02v0.04
+ c0,3.88,2.82,7.06,6.7,7.06S163.48,249.11,163.48,245.23z"/>
+ <path class="st0" d="M167.89,237.34h1.1l10.83,13.65v-13.65h1.12v15.69h-0.87l-11.05-13.94v13.94h-1.12V237.34z"/>
+</g>
+<path class="st1" d="M82.66,189.23c0.85-2.75,3.77-4.8,7.28-4.8c1.2,0,2.31,0.26,3.31,0.68c2.21-1.47,4.94-2.35,7.92-2.35h0.02
+ c0.92-1.86,3.29-3.19,6.11-3.19c0.74,0,1.45,0.1,2.12,0.27c-0.09-2.28,0.27-4.66,1.13-7.16c1-2.89,2.45-5.65,3.97-8.4
+ c-0.35-4.12-0.62-7.78-5.78-9.28c-1.92-0.56-3.92-0.73-5.88-0.96l-0.01,0l0-0.01c-0.84-0.1-1.68-0.22-2.5-0.38
+ c-14.17,14.76-34.15-20.68-34.15-20.68c44.1-6.84,35.81,15.64,35.81,15.64c-3.2-1.56-4.08-3.53-6.52-5.88
+ c-5.57-5.35-18.87-6.29-18.87-6.29c15.92,4.07,18.09,11.78,24.35,14.25c1.42,0.32,2.93,0.44,4.38,0.6c2.8,0.3,5.54,0.82,7.87,2.32
+ c2.41,1.55,3.49,3.48,4.04,5.65c1.74-3.32,3.24-6.7,3.81-10.34c0.73-4.65,0.06-10.04-3.24-13.85c-3.05-3.52-7.17-6.18-10.43-9.55
+ c-3.48-3.61-5.79-8.06-5.88-12.81c-1.76-3.85-4.62-8.32-7.24-10.06C82.9,113.34,67.9,85.58,67.9,85.58
+ c34.98-4.88,29.2,13.09,29.2,13.09c-8.4-9.39-18.79-8.55-18.79-8.55c8.4,2.67,15.03,8.03,18.89,11.71l0.53,0.53
+ c1.57,1.64,3.17,3.39,4.51,5.27c1.36-5.15,4.53-12.36,7.02-16.66c0,0,8.4-14.82,22.54-24.07c0,0-10.78,1.24-22.39,18.99
+ c0,0-15.42-24.19,34.42-28.66c0,0-3.43,43.94-30.38,35.4c-4.68,7.04-7.75,15.11-7.12,20.79c0.62,5.54,4.5,9.44,8.78,13.08
+ c1.14-5.84,5.35-10.87,11.54-13.61c4.95-1.97,12.25-3.86,19.07-4.27c0,0-13.33-3.04-23.47,3.89c0,0,0.17-20.29,36.09-5.56
+ c0,0-26,26.34-34.35,10.64c-3.96,2.61-6.46,6.99-5.81,11.52c2.32,2.03,4.48,4.22,5.79,6.92c1.83,3.79,2.48,8.21,1.98,12.32
+ c-0.96,7.9-5.9,14.62-9.28,21.79c-1.38,2.92-2.7,6.13-2.72,9.37c1.69-0.47,3.52-0.73,5.44-0.73c7.23,0,13.32,3.59,15.29,8.52
+ c2.93,0.31,5.24,2.03,5.66,4.21c2.11,1.3,3.78,3.12,4.79,5.24H76.55C78.02,193.62,80.14,190.16,82.66,189.23"/>
+<g>
+ <path class="st0" d="M43.54,206.39h18v3.82H47.8v6.31h12.17v3.81H47.8v6.52h13.91v3.82H43.54V206.39z"/>
+ <path class="st0" d="M64.55,218.6v-0.07c0-6.9,5.17-12.56,12.52-12.56c4.47,0,7.18,1.56,9.5,3.78l-2.74,3.16
+ c-1.94-1.8-4.02-3.02-6.8-3.02c-4.61,0-8.01,3.82-8.01,8.57v0.07c0,4.75,3.36,8.6,8.01,8.6c2.98,0,4.89-1.18,6.97-3.12l2.74,2.77
+ c-2.53,2.64-5.31,4.3-9.85,4.3C69.83,231.09,64.55,225.57,64.55,218.6z"/>
+ <path class="st0" d="M90.22,206.39h4.27v20.39h12.76v3.88H90.22V206.39z"/>
+ <path class="st0" d="M110.93,206.39h4.27v24.28h-4.27V206.39z"/>
+ <path class="st0" d="M120.67,206.39h9.57c5.69,0,9.23,3.23,9.23,8.12v0.07c0,5.45-4.37,8.29-9.71,8.29h-4.82v7.8h-4.27V206.39z
+ M129.9,219.02c3.23,0,5.24-1.8,5.24-4.34v-0.07c0-2.84-2.05-4.33-5.24-4.33h-4.96v8.74H129.9z"/>
+ <path class="st0" d="M141.21,227.13l2.57-3.05c2.32,2.01,4.68,3.16,7.67,3.16c2.64,0,4.3-1.25,4.3-3.05v-0.07
+ c0-1.73-0.97-2.67-5.48-3.71c-5.17-1.25-8.08-2.77-8.08-7.25v-0.07c0-4.16,3.47-7.04,8.29-7.04c3.54,0,6.35,1.08,8.81,3.05
+ l-2.29,3.23c-2.19-1.63-4.37-2.5-6.59-2.5c-2.5,0-3.95,1.28-3.95,2.88v0.07c0,1.87,1.11,2.71,5.79,3.82
+ c5.13,1.25,7.77,3.09,7.77,7.11v0.07c0,4.54-3.57,7.25-8.67,7.25C147.62,231.02,144.12,229.73,141.21,227.13z"/>
+ <path class="st0" d="M163.99,206.39h18v3.82h-13.73v6.31h12.17v3.81h-12.17v6.52h13.91v3.82h-18.17V206.39z"/>
+</g>
+<path class="st1" d="M47.66,62.99c19.6-30.57,58.84-41.24,91.57-26.55c-0.72-0.5-1.45-1.01-2.2-1.49
+ c-33.51-21.49-78.05-11.84-99.47,21.57c-21.43,33.4-11.62,77.91,21.89,99.4c0.75,0.48,1.51,0.93,2.27,1.38
+ C34.73,133.68,28.06,93.56,47.66,62.99"/>
+</svg>
diff --git a/frontend/src/components/404.vue b/frontend/src/components/404.vue
new file mode 100644
index 0000000..6f79a09
--- /dev/null
+++ b/frontend/src/components/404.vue
@@ -0,0 +1,21 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <div>
+ 404
+ </div>
+</template>
+
+<script>
+ export default {}
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/charts/DoughnutChart.js b/frontend/src/components/charts/DoughnutChart.js
new file mode 100644
index 0000000..2f0e7ce
--- /dev/null
+++ b/frontend/src/components/charts/DoughnutChart.js
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import {Doughnut, mixins} from "vue-chartjs";
+
+const {reactiveProp} = mixins
+
+export default {
+ extends: Doughnut,
+ mixins: [reactiveProp],
+ props: ['options'],
+ mounted() {
+ this.renderChart(this.chartData, this.options);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/finder.vue b/frontend/src/components/finder.vue
new file mode 100644
index 0000000..592de5d
--- /dev/null
+++ b/frontend/src/components/finder.vue
@@ -0,0 +1,347 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-clipboard="http://www.w3.org/1999/xhtml">
+ <el-container style="height: 100%">
+ <el-dialog
+ :title="this.getAddFileTitle()"
+ :visible.sync="transferViewVisible"
+ width="40%" :close-on-click-modal=false>
+ <TransferFile :fileType="currentMenuItem" :transferViewVisible="transferViewVisible"
+ @transferFileFinishNotify="()=>{this.transferViewVisible = false; this.go(1)}"
+ style="margin-top: -20px"/>
+ </el-dialog>
+
+ <el-header>
+ <view-menu subject="finder"
+ :fileType="currentMenuItem"
+ :title="this.getAddFileTitle()"
+ @chooseMenu="item => this.currentMenuItem= item"
+ @addFile="() => this.transferViewVisible = true"/>
+ </el-header>
+
+ <el-dialog
+ :title="$t('jifa.prompt')"
+ :visible="true"
+ v-if="fileToDelete"
+ width="25%"
+ :before-close="cancelDelete">
+ <span style="font-size: 20px; color: #e6a23c"><i class="el-icon-warning"/> </span>
+ <span style="font-size: 18px">{{ $t('jifa.deletePrompt') }}</span>
+ <span slot="footer" class="dialog-footer">
+ <el-button @click="cancelDelete">{{ $t('jifa.cancel') }}</el-button>
+ <el-button @click="doDelete" type="primary">{{ $t('jifa.confirm') }}</el-button>
+ </span>
+ </el-dialog>
+
+ <el-main v-loading.fullscreen.lock="loading" style="height: 100%">
+ <el-row type="flex" v-for="row in rows" :key="row">
+ <el-col :span="6" v-for="col in (row < rows ? cols : colsOfLastRow)" :key="col">
+ <el-card class="box-card" shadow="hover" style="margin: 20px">
+ <div>
+ <el-row type="flex">
+ <el-col :span="16">
+ <p style='font-size: 15px; margin:0 auto; white-space: nowrap; text-overflow:ellipsis; overflow:hidden;
+ color: #606266;'>
+ <i class="el-icon-document"></i>
+ {{file(row, col).displayName ? file(row, col).displayName : file(row, col).name}}
+ </p>
+ </el-col>
+
+ <el-col :span="8" align="right">
+ <span>
+ <el-link icon="el-icon-document-copy" v-clipboard:copy="file(row, col).name"
+ :underline="false" target="_blank"/>
+ </span>
+
+ <span v-if="file(row,col).hasOwnProperty('displayName')">
+ <el-divider direction="vertical"></el-divider>
+ <el-link icon="el-icon-edit" :underline="false" @click="updateFile(file(row,col))"/>
+ </span>
+
+ <span v-if="file(row,col).hasOwnProperty('shared')">
+ <el-divider direction="vertical"></el-divider>
+ <el-link :icon="file(row, col).shared ? 'el-icon-unlock' : 'el-icon-lock'"
+ v-on:click="toggleSharedState(file(row, col))"
+ :underline="false"
+ target="_blank"/>
+ </span>
+
+ <span v-if="downloadable(file(row,col))">
+ <el-divider direction="vertical"></el-divider>
+ <el-link icon="el-icon-download" :underline="false"
+ :href="service('/file/download/' + currentMenuItem + '/' + file(row, col).name)"
+ target="_blank"/>
+ </span>
+
+ <span v-if="canDelete(file(row,col))">
+ <el-divider direction="vertical"></el-divider>
+ <el-link icon="el-icon-delete" :underline="false"
+ v-on:click="fileToDelete = file(row, col).name"/>
+ </span>
+ </el-col>
+ </el-row>
+ <el-row :align='"middle"' type="flex">
+ <el-col :span="12">
+ <p style="font-size: 12px; margin: 10px auto 7px; white-space: nowrap; color: #606266;" align="left">
+ {{toSizeString(file(row, col).size)}}</p>
+ </el-col>
+ <el-col :span="12">
+ <p style="font-size: 12px; margin:10px auto 7px; white-space: nowrap; color: #606266;" align="right">
+ {{formatDate(new Date(file(row, col).creationTime), "yyyy-MM-dd HH:mm:ss")}}</p>
+ </el-col>
+ </el-row>
+ <el-row>
+ <hr style="margin: 0 auto 7px;"/>
+ </el-row>
+
+ <el-row type="flex" justify="space-around" style="margin-bottom: -15px">
+
+ <el-col :span="8" align="middle"
+ v-if="file(row, col).transferState === 'NOT_STARTED' || file(row, col).transferState ==='IN_PROGRESS'">
+ <el-button type="text"><i class="el-icon-loading"></i> {{$t('jifa.transferring')}}</el-button>
+ </el-col>
+
+ <el-col :span="8" align="middle"
+ v-if="file(row, col).transferState === 'ERROR'">
+ <el-button type="text"><i class="el-icon-error"></i> {{$t('jifa.transferError')}}</el-button>
+ </el-col>
+
+ <el-col :span="8" align="middle"
+ v-if="file(row, col).transferState === 'SUCCESS'">
+ <router-link
+ :to="{path : analysisPath() , query: {file: file(row, col).name, displayName: file(row, col).displayName} }">
+ <el-button type="text"><i class="el-icon-view"></i> {{$t('jifa.analyze')}}</el-button>
+ </router-link>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <el-row type="flex" justify="space-around" style="margin-top: 77px">
+ <el-col :span="8">
+ <el-pagination
+ background
+ layout="prev, pager, next"
+ :current-page="page"
+ :page-size="pageSize"
+ :total="totalSize"
+ @current-change="handleCurrentPageChange"
+ hide-on-single-page
+ align="center">
+ </el-pagination>
+ </el-col>
+ </el-row>
+ </el-main>
+ <el-footer>
+ <Footer/>
+ </el-footer>
+ </el-container>
+</template>
+
+<script>
+ import axios from 'axios'
+ import Footer from "./footer"
+
+
+ import {formatDate} from 'element-ui/src/utils/date-util'
+ import {service, toSizeString} from '../util'
+ import TransferFile from './transferFile'
+ import ViewMenu from './menu/ViewMenu'
+
+ const defaultMenuItem = 'HEAP_DUMP'
+
+ export default {
+ components: {TransferFile, ViewMenu, Footer},
+ data() {
+ return {
+ files: [],
+ cols: 4,
+ rows: 0,
+ colsOfLastRow: 0,
+
+ page: 0,
+ pageSize: 12,
+ totalSize: 0,
+
+ loading: false,
+ defaultMenuItem,
+
+ transferViewVisible: false,
+ fileToDelete: null,
+
+ currentMenuItem: defaultMenuItem,
+ }
+ },
+ methods: {
+ getAddFileTitle() {
+ switch (this.currentMenuItem) {
+ case "HEAP_DUMP":
+ return this.$i18n.t('jifa.addHeapDumpFile');
+ default:
+ return this.$i18n.t('jifa.addFile');
+ }
+ },
+
+ file(row, col) {
+ return this.files[(row - 1) * this.cols + col - 1]
+ },
+
+ service,
+ formatDate,
+ toSizeString,
+
+ handleCurrentPageChange(page) {
+ this.go(page)
+ },
+
+ analysisPath() {
+ let lowered = this.currentMenuItem.toLowerCase().split("_");
+
+ if (lowered.length === 0) {
+ return "";
+ } else if (lowered.length === 1) {
+ return lowered[0];
+ }
+
+ let finalPath = lowered[0];
+ for (let i = 1; i < lowered.length; i++) {
+ if (lowered[i].length === 0) {
+ continue;
+ }
+ finalPath += lowered[i][0].toUpperCase();
+ if (lowered[i].length > 1) {
+ finalPath += lowered[i].substring(1);
+ }
+ }
+ return finalPath;
+ },
+
+ go(page) {
+ this.page = page
+ this.fetchFiles()
+ },
+
+ toggleSharedState(file) {
+ let formData = new FormData()
+ formData.append('name', file.name)
+ axios.post(service(file.shared ? "/file/unsetShared" : "/file/setShared"),
+ new URLSearchParams(formData)).then(() => {
+ file.shared = !file.shared
+ })
+ },
+
+ downloadable(file) {
+ return file.downloadble && this.transferIsSuccess(file)
+ },
+
+ transferIsSuccess(file) {
+ return file.transferState === 'SUCCESS'
+ },
+
+ canDelete(file) {
+ return file.transferState === 'SUCCESS' || file.transferState === 'ERROR'
+ },
+
+ cancelDelete() {
+ this.fileToDelete = null
+ this.$message({
+ type: 'info',
+ message: this.$t('jifa.deleteCanceled'),
+ duration: 1000
+ });
+ },
+
+ doDelete() {
+ if (!this.fileToDelete) {
+ return
+ }
+ let formData = new FormData()
+ formData.append('type', this.currentMenuItem)
+ formData.append('name', this.fileToDelete)
+ axios.post(service("/file/delete"), new URLSearchParams(formData)).then(() => {
+ this.fileToDelete = null
+ this.$message({
+ message: this.$t('jifa.deleteSuccessPrompt'),
+ type: 'success',
+ duration: 500,
+ onClose: () => {
+ if (this.files.length === 1) {
+ this.go(this.page > 1 ? this.page - 1 : this.page)
+ } else {
+ this.go(this.page)
+ }
+ }
+ });
+ }).catch(() => {
+ this.fileToDelete = null
+ this.$message({
+ message: this.$t('jifa.deleteFailedPrompt'),
+ type: 'error',
+ duration: 1000
+ });
+ })
+ },
+
+ fetchFiles() {
+ this.loading = true;
+ axios.get(service('/files'), {
+ params: {
+ type: this.currentMenuItem,
+ page: this.page,
+ pageSize: this.pageSize
+ }
+ }).then(resp => {
+ this.files = resp.data.data
+ this.totalSize = resp.data.totalSize
+ if (this.files.length > 0) {
+ this.rows = Math.ceil(this.files.length / this.cols)
+ let mod = this.files.length % this.cols
+ this.colsOfLastRow = mod > 0 ? mod : this.cols
+ } else {
+ this.rows = 0
+ this.colsOfLastRow = 0
+ }
+ this.loading = false
+ })
+ },
+
+ updateFile(file) {
+ this.$prompt('New display name: ', 'Edit', {
+ confirmButtonText: this.$t("jifa.confirm"),
+ cancelButtonText: this.$t('jifa.cancel'),
+ inputValue: file.displayName
+ }).then(({value}) => {
+ let formData = new FormData()
+ formData.append('name', file.name)
+ formData.append('displayName', value)
+ axios.post(service("/file/updateDisplayName"), new URLSearchParams(formData))
+ .then(() => {
+ this.go(this.page)
+ })
+ })
+ }
+ },
+
+ watch: {
+ currentMenuItem() {
+ this.go(1)
+ },
+ },
+
+ created() {
+ this.go(1)
+ }
+ }
+</script>
diff --git a/frontend/src/components/footer.vue b/frontend/src/components/footer.vue
new file mode 100644
index 0000000..28db119
--- /dev/null
+++ b/frontend/src/components/footer.vue
@@ -0,0 +1,18 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+</template>
+
+<script>
+ export default {}
+</script>
diff --git a/frontend/src/components/heapdump/ClassLoaders.vue b/frontend/src/components/heapdump/ClassLoaders.vue
new file mode 100644
index 0000000..84e7ea2
--- /dev/null
+++ b/frontend/src/components/heapdump/ClassLoaders.vue
@@ -0,0 +1,259 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div style="height: 100%">
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-item divider></v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <el-table ref="recordTable"
+ :data="tableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ :load="loadChildren"
+ lazy
+ :span-method="spanMethod"
+ height="100%"
+ :indent=8
+ v-loading="loading"
+ >
+ <el-table-column label="Class Name">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRecord" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu>
+ <img :src="scope.row.classLoader ? (scope.row.hasParent ? classLoaderOutboundIcon : classLoaderIcon) : classIcon"/>
+ <strong>{{ scope.row.prefix }}</strong>
+ {{scope.row.label}}
+ </span>
+
+ <span v-if="scope.row.isSummary">
+ <img :src="sumIcon" v-if="records.length >= totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchClassLoaders" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{totalSize}}
+ </span>
+
+ <span v-if="scope.row.isChildrenSummary">
+ <img :src="sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="sumPlusIcon"
+ @dblclick="fetchChildren(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column label="Defined Classes" prop="definedClasses">
+ </el-table-column>
+
+ <el-table-column label="No. of Instances" prop="numberOfInstances">
+ </el-table-column>
+ </el-table>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import {ICONS} from "./IconHealper";
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 6]
+ } else if (index >= 1 && index <= 5) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ fetchSummary() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'classLoaderExplorer/summary')).then(resp => {
+ this.definedClasses = resp.data.definedClasses
+ this.numberOfInstances = resp.data.numberOfInstances
+ this.totalSize = resp.data.totalSize
+ if (this.totalSize > 0) {
+ this.fetchClassLoaders()
+ }
+ })
+ },
+ fetchClassLoaders() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'classLoaderExplorer/classLoader'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let records = resp.data.data
+ records.forEach(record => this.records.push({
+ rowKey: rowKey++,
+
+ objectId: record.objectId,
+ prefix: record.prefix,
+ label: record.label,
+ classLoader: record.classLoader,
+ hasParent: record.hasParent,
+ definedClasses: record.definedClasses,
+ numberOfInstances: record.numberOfInstances,
+
+ hasChildren: record.classLoader,
+ isRecord: true,
+ }))
+
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ definedClasses: this.definedClasses,
+ numberOfInstances: this.numberOfInstances,
+ isSummary: true
+ })
+
+ this.nextPage++
+ this.loading = false
+ })
+ },
+
+ loadChildren(tree, treeNode, resolve) {
+ this.fetchChildren(tree.rowKey, tree.objectId, 1, resolve)
+ },
+
+ fetchChildren(parentRowKey, objectId, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'classLoaderExplorer/children'), {
+ params: {
+ classLoaderId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['recordTable'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(record => {
+ loaded.push({
+ rowKey: rowKey++,
+
+ objectId: record.objectId,
+ prefix: record.prefix,
+ label: record.label,
+ classLoader: record.classLoader,
+ hasParent: record.hasParent,
+ definedClasses: record.classLoader ? record.definedClasses : null,
+ numberOfInstances: record.numberOfInstances,
+
+ hasChildren: record.classLoader,
+
+ isRecord: true,
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isChildrenSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+ },
+ data() {
+ return {
+ classIcon: ICONS.objects.class,
+ classLoaderIcon: ICONS.objects.classloader_obj,
+ classLoaderOutboundIcon: ICONS.objects.out.classloader_obj,
+
+ sumIcon: ICONS.misc.sumIcon,
+ sumPlusIcon: ICONS.misc.sumPlusIcon,
+
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+
+ loading: false,
+
+ definedClasses: 0,
+ numberOfInstances: 0,
+
+ totalSize: 0,
+ nextPage: 1,
+ pageSize: 25,
+ records: [],
+ tableData: [],
+
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+ }
+ },
+ created() {
+ this.fetchSummary()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/ColorHelper.js b/frontend/src/components/heapdump/ColorHelper.js
new file mode 100644
index 0000000..bc76413
--- /dev/null
+++ b/frontend/src/components/heapdump/ColorHelper.js
@@ -0,0 +1,50 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export const PIE_COLORS = [
+ [96, 127, 143],
+ [98, 146, 147],
+ [110, 138, 79],
+ [140, 101, 87],
+ [123, 96, 114],
+ [101, 129, 120],
+ [148, 132, 75],
+ [150, 103, 110],
+
+ [152, 173, 183],
+ [154, 185, 185],
+ [162, 180, 141],
+ [181, 156, 147],
+ [170, 152, 164],
+ [156, 175, 168],
+ [186, 176, 139],
+ [188, 157, 162],
+
+ [68, 105, 125],
+ [21, 101, 112],
+ [85, 118, 48],
+ [119, 74, 57],
+ [100, 68, 89],
+ [73, 108, 96],
+ [129, 110, 44],
+ [132, 76, 84]
+]
+
+export const REMAINDER_COLOR= [220, 220, 220]
+
+export function a2rgb(c) {
+ let r = c[0]
+ let g = c[1]
+ let b = c[2]
+ return '#' + r.toString(16) + g.toString(16) + b.toString(16)
+}
+
diff --git a/frontend/src/components/heapdump/CommonType.js b/frontend/src/components/heapdump/CommonType.js
new file mode 100644
index 0000000..6110ba2
--- /dev/null
+++ b/frontend/src/components/heapdump/CommonType.js
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export const OBJECT_TYPE = {
+ CLASS: 1,
+ CLASSLOADER: 2,
+ ARRAY: 3,
+ NORMAL: 4
+}
+
+export const CLASS_TYPE = {
+ NEW: 0,
+ MIXED: 1,
+ OLD_FAD: 2
+}
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/DirectByteBuffer.vue b/frontend/src/components/heapdump/DirectByteBuffer.vue
new file mode 100644
index 0000000..c79f186
--- /dev/null
+++ b/frontend/src/components/heapdump/DirectByteBuffer.vue
@@ -0,0 +1,161 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div style="height: 100%">
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <el-table :data="tableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :span-method="spanMethod"
+ height="100%"
+ :indent=8
+ v-loading="loading"
+ >
+ <el-table-column label="Label">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRecord" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu
+ style="cursor: pointer">
+ <img :src="instanceIcon"/> {{scope.row.label}}
+ </span>
+
+ <span v-if="scope.row.isSummary">
+ <img :src="sumIcon" v-if="records.length >= totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchRecords" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column label="position" prop="position">
+ </el-table-column>
+
+ <el-table-column label="limit" prop="limit">
+ </el-table-column>
+
+ <el-table-column label="capacity" prop="capacity">
+ </el-table-column>
+
+ </el-table>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 4]
+ } else if (index >= 1 && index <= 3) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ fetchSummary() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'directByteBuffer/summary')).then(resp => {
+ this.totalSize = resp.data.totalSize
+ this.position = resp.data.position
+ this.limit = resp.data.limit
+ this.capacity = resp.data.capacity
+ if (this.totalSize > 0) {
+ this.fetchRecords()
+ } else {
+ this.loading = false
+ }
+ })
+ },
+ fetchRecords() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'directByteBuffer/records'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let records = resp.data.data
+ records.forEach(record => this.records.push({
+ rowKey: rowKey++,
+
+ objectId: record.objectId,
+ label: record.label,
+ position: record.position,
+ limit: record.limit,
+ capacity: record.capacity,
+
+ isRecord: true,
+ }))
+
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ position: this.position,
+ limit: this.limit,
+ capacity: this.capacity,
+ isSummary: true
+ })
+
+ this.nextPage++
+ this.loading = false
+ })
+ },
+ },
+ data() {
+ return {
+ instanceIcon: require('../../assets/heap/objects/instance_obj.gif'),
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+
+ loading: false,
+
+ position: 0,
+ limit: 0,
+ capacity: 0,
+
+ totalSize: 0,
+ nextPage: 1,
+ pageSize: 25,
+ records: [],
+ tableData: [],
+
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+ }
+ },
+ created() {
+ this.fetchSummary()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/DominatorTree.vue b/frontend/src/components/heapdump/DominatorTree.vue
new file mode 100644
index 0000000..414c9d5
--- /dev/null
+++ b/frontend/src/components/heapdump/DominatorTree.vue
@@ -0,0 +1,268 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div style="height: 100%; position: relative">
+ <div style="height: 40px; padding-top: 10px" align="center">
+ <el-radio-group v-model="grouping" @change="changeGrouping">
+ <el-radio label="NONE">Object</el-radio>
+ <el-radio label="BY_CLASS">Class</el-radio>
+ <!--<el-radio label="BY_CLASSLOADER">Class Loader</el-radio>-->
+ <!--<el-radio label="BY_PACKAGE">Package</el-radio>-->
+ </el-radio-group>
+ </div>
+
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-item divider></v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <div v-loading="loading" style="position: absolute; top: 40px; left: 0; right: 0; bottom: 0;">
+ <el-table
+ ref='recordTable' :data="tableData"
+ :highlight-current-row="true"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ :load="loadChildren"
+ height="100%"
+ :span-method="spanMethod"
+ :indent=8
+ lazy
+ fit>
+ <el-table-column label="Class Name" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isResult" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu>
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ {{ scope.row.label }}
+ <span style="font-weight: bold; color: #909399">
+ {{ scope.row.suffix }}
+ </span>
+ </span>
+
+ <span v-if="scope.row.isSummaryItem">
+ <img :src="ICONS.misc.sumIcon" v-if="records.length >= totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchNextPageData" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{totalSize}}
+ </span>
+
+ <span v-if="scope.row.isChildrenSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchChildren(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column v-if="grouping!=='NONE'" label="Objects">
+ <template slot-scope="scope">
+ {{ grouping !== "NONE" ? scope.row.objects : ''}}
+ </template>
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+ <el-table-column label="Retained Heap" prop="retainedHeap">
+ </el-table-column>
+ <el-table-column label="Percentage" prop="percent">
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {getIcon, ICONS} from "./IconHealper";
+ import {heapDumpService} from "../../util";
+
+ let rowKey = 1
+
+ export default {
+ props: ['file'],
+ data() {
+ return {
+ ICONS,
+ loading: false,
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ grouping: 'NONE',
+
+ nextPage: 1,
+ pageSize: 25,
+ totalSize: 0,
+ records: [],
+ tableData: [],
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+ }
+ },
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 6]
+ } else if (index >= 1 && index <= 5) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ clear() {
+ this.nextPage = 1
+ this.totalSize = 0
+ this.records = []
+ },
+ changeGrouping() {
+ this.clear()
+ this.fetchNextPageData()
+ },
+ getIconWrapper(gCRoot, objectType) {
+ if (this.grouping === 'BY_CLASS') {
+ return ICONS.objects.class
+ }
+ return getIcon(gCRoot, objectType)
+ },
+ loadChildren(tree, treeNode, resolve) {
+ this.fetchChildren(tree.rowKey, tree.objectId, 1, resolve)
+ },
+ fetchChildren(parentRowKey, objectId, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'dominatorTree/children'), {
+ params: {
+ parentObjectId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ grouping: this.grouping
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['recordTable'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: d.objectId,
+ icon: this.getIconWrapper(d.gCRoot, d.objectType),
+ label: d.label,
+ suffix: d.suffix,
+ objects: d.objects,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ percent: (d.percent * 100).toFixed(2) + '%',
+ hasChildren: true,
+ isResult: true
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isChildrenSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+ fetchNextPageData() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'dominatorTree/roots'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ grouping: this.grouping
+ }
+ }).then(resp => {
+ this.totalSize = resp.data.totalSize
+ let data = resp.data.data
+ data.forEach(d => {
+ this.records.push({
+ rowKey: rowKey++,
+ objectId: d.objectId,
+ icon: this.getIconWrapper(d.gCRoot, d.objectType),
+ label: d.label,
+ suffix: d.suffix,
+ objects: d.objects,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ percent: (d.percent * 100).toFixed(2) + '%',
+ hasChildren: this.grouping !== 'BY_CLASS',
+ isResult: true
+ })
+ })
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ isSummaryItem: true
+ })
+ this.nextPage++
+ this.loading = false
+ })
+ },
+ },
+ created() {
+ this.fetchNextPageData()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/DuplicatedClasses.vue b/frontend/src/components/heapdump/DuplicatedClasses.vue
new file mode 100644
index 0000000..64eec6c
--- /dev/null
+++ b/frontend/src/components/heapdump/DuplicatedClasses.vue
@@ -0,0 +1,209 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <div style="height: 100%">
+ <el-table
+ ref="table"
+ :data="records"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ height="100%"
+ :indent=8
+ lazy
+ v-loading="loading"
+ :load="fetchClassLoaders"
+ :span-method="tableSpanMethod">
+ <el-table-column label="Class Name / Class Loader" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isClassItem">
+ <img :src="ICONS.objects.class"/> {{scope.row.label}}
+ </span>
+
+ <span v-if="scope.row.isClassLoaderItem" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon"/> {{scope.row.label}}
+ <span style="font-weight: bold; color: #909399" v-if="scope.row.suffix">{{ " " + scope.row.suffix}}</span>
+ </span>
+
+ <span v-if="scope.row.isCldSummaryItem">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchMoreClassLoaders(scope.row)" style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+
+ <span v-if="scope.row.isSummaryItem">
+ <img :src="ICONS.misc.sumIcon" v-if="currentSize >= totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchDuplicatedClasses" style="cursor: pointer" v-else/>
+ {{ currentSize }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column label="ClassLoader Counts" prop="classLoaderCount">
+ </el-table-column>
+
+ <el-table-column label="Defined Classes" prop="definedClassesCount">
+ </el-table-column>
+
+ <el-table-column label="Num of Instances" prop="instantiatedObjectsCount">
+ </el-table-column>
+ </el-table>
+
+ </div>
+</template>
+
+<script>
+
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import {getIcon, ICONS} from "./IconHealper";
+ import {OBJECT_TYPE} from './CommonType'
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ methods: {
+ tableSpanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 4]
+ } else if (index >= 1 && index <= 3) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ doFetchClassLoaders(parentRowKey, index, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'duplicatedClasses/classLoaders'), {
+ params: {
+ index: index,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0
+ let loaded = this.$refs['table'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+ let res = resp.data.data
+ for (let i = 0; i < res.length; i++) {
+ loaded.push({
+ rowKey: rowKey++,
+ isClassLoaderItem: true,
+ label: res[i].label,
+ objectId: res[i].objectId,
+ suffix: res[i].suffix,
+ definedClassesCount: res[i].definedClassesCount,
+ instantiatedObjectsCount: res[i].instantiatedObjectsCount,
+ icon: getIcon(res[i].gCRoot, OBJECT_TYPE.CLASSLOADER)
+ })
+ }
+ loaded.push({
+ rowKey: rowKey++,
+ parentRowKey: parentRowKey,
+ isCldSummaryItem: true,
+ index: index,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+ fetchMoreClassLoaders(summary) {
+ this.doFetchClassLoaders(summary.parentRowKey, summary.index, summary.nextPage, summary.resolve)
+ },
+ fetchClassLoaders(tree, treeNode, resolve) {
+ this.doFetchClassLoaders(tree.rowKey, tree.index, 1, resolve)
+ },
+ fetchDuplicatedClasses() {
+ this.loading = true
+ if (this.nextPage > 1) {
+ this.records.splice(this.records.length - 1, 1)
+ }
+ axios.get(heapDumpService(this.file, 'duplicatedClasses/classes'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ this.totalSize = resp.data.totalSize
+ let res = resp.data.data
+ let index = this.currentSize
+ let tmp = []
+ for (let i = 0; i < res.length; i++) {
+ tmp.push({
+ rowKey: rowKey++,
+ label: res[i].label,
+ icon: this.classIcon,
+ index: index++,
+ classLoaderCount: res[i].count,
+ currentSize: 0,
+ hasChildren: res[i].count > 0,
+ isClassItem: true,
+ })
+ }
+ this.nextPage++
+ this.currentSize += res.length
+ tmp.forEach(t => this.records.push(t))
+ if (this.records.length > 0) {
+ this.records.push({
+ rowKey: rowKey++,
+ isSummaryItem: true
+ })
+ }
+ this.loading = false
+ })
+ },
+
+ },
+ data() {
+ return {
+ ICONS,
+ loading: true,
+ records: [],
+ nextPage: 1,
+ pageSize: 25,
+ currentSize: 0,
+ totalSize: 0,
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ }
+ },
+ created() {
+ this.fetchDuplicatedClasses()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/DynamicResultSlot.vue b/frontend/src/components/heapdump/DynamicResultSlot.vue
new file mode 100644
index 0000000..5e40a63
--- /dev/null
+++ b/frontend/src/components/heapdump/DynamicResultSlot.vue
@@ -0,0 +1,557 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div class="resultDiv">
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-item divider></v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" style="height: 100%">
+ <el-tab-pane
+ v-for="(item) in editableTabs"
+ :key="item.name"
+ :label="item.title"
+ :name="item.name">
+ <el-table v-if="item.isObjRefsTab"
+ ref="resultContainer"
+ v-loading="item.loading"
+ :data="item.topItems"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ :load="item.load"
+ row-key="rowKey"
+ lazy
+ :indent=8
+ height="100%">
+ <el-table-column label="Class Name" width="1000px" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isResult" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu>
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ <strong>{{ scope.row.prefix }}</strong>
+ {{ scope.row.label }}
+ <span style="font-weight: bold; color: #909399">
+ {{ scope.row.suffix }}
+ </span>
+ </span>
+
+ <span v-if="scope.row.isBoundsSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchObjBounds(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+ <el-table-column label="Retained Heap" prop="retainedHeap">
+ </el-table-column>
+ </el-table>
+
+
+ <el-table v-if="item.isClassRefsTab"
+ ref="resultContainer"
+ v-loading="item.loading"
+ :data="item.topItems"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ :load="item.load"
+ row-key="rowKey"
+ lazy
+ :indent=8
+ height="100%">
+ <el-table-column label="Class Name" width="1000px" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isResult" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu>
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ {{ scope.row.label }}
+ </span>
+
+ <span v-if="scope.row.isBoundsSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchClassBounds(scope.row.parentRowKey, scope.row.objectIds, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="Objects" prop="objects">
+ </el-table-column>
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+ </el-table>
+
+ <div v-if="item.isPathToGCRootsTab" style="height: 100%; overflow: scroll">
+ <el-tree ref="resultContainer"
+ v-loading="item.loading"
+ :data="item.treeData"
+ node-key="objectId"
+ :expand-on-click-node="false"
+ default-expand-all>
+ <span class="custom-tree-node" style="font-size: 12px" slot-scope="{ node, data }"
+ @click="$emit('setSelectedObjectId', data.objectId)"
+ @contextmenu="contextMenuTargetObjectId = data.objectId; contextMenuTargetObjectLabel = data.label"
+ v-contextmenu:contextmenu>
+ <span>
+ <img :src="data.origin ? getIcon(data.gCRoot, data.objectType) : getInboundIcon(data.gCRoot, data.objectType)"
+ style="margin-right: 5px"/>
+ <strong>{{ data.prefix }}</strong>
+ {{ data.label }}
+ <span style="font-weight: bold; color: #909399">
+ {{ data.suffix }}
+ </span>
+ </span>
+
+ <span>
+ {{ data.shallowSize }} / {{ data.retainedSize }}
+ </span>
+ </span>
+ </el-tree>
+ <el-divider><i v-if="item.hasMore" :class="item.loading ? 'el-icon-loading':'el-icon-circle-plus-outline'"
+ style="font-size: 25px; cursor: pointer"
+ @dblclick="loadMorePathToGCRootsOfObj(item)"></i></el-divider>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+ </div>
+</template>
+<script>
+ import axios from 'axios'
+ import {
+ getClassRefInboundIcon,
+ getClassRefOutboundIcon,
+ getIcon,
+ getInboundIcon,
+ getOutboundIcon,
+ ICONS
+ } from "./IconHealper";
+ import {heapDumpService} from "../../util";
+
+ let rowKey = 1
+
+ export default {
+ props: ['file'],
+ data() {
+ return {
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ tabIndex: 0,
+ editableTabsValue: null,
+ editableTabs: [],
+ ICONS,
+ pageSize: 25,
+
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+ }
+ },
+ methods: {
+ getIcon,
+ getInboundIcon,
+ getOutboundIcon,
+ currentIndex() {
+ for (let i = 0; i < this.editableTabs.length; i++) {
+ if (this.editableTabs[i].name === this.editableTabsValue) {
+ return i;
+ }
+ }
+ },
+ buildTitle(prefix, label) {
+ return '「' + prefix + '」' + label
+ },
+
+ loadObjBounds(tree, treeNode, resolve) {
+ this.fetchObjBounds(tree.rowKey, tree.objectId, 1, resolve)
+ },
+
+ fetchObjBounds(parentRowKey, objectId, page, resolve) {
+ let index = this.currentIndex()
+ let tab = this.editableTabs[index]
+ let outbound = tab.outbound
+ let table = this.$refs.resultContainer[index]
+ tab.loading = true
+ axios.get(heapDumpService(this.file, outbound ? 'outbounds' : 'inbounds'), {
+ params: {
+ objectId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = table.store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ icon: outbound ? getOutboundIcon(d.gCRoot, d.objectType) : getInboundIcon(d.gCRoot, d.objectType),
+ prefix: d.prefix,
+ label: d.label,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ hasChildren: true,
+ objectId: d.objectId,
+ isResult: true
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isBoundsSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ tab.loading = false
+ })
+ },
+
+ outgoingRefsOfObj(objectId, label) {
+ this.boundsOfObj(objectId, label, true)
+ },
+
+ incomingRefsOfObj(objectId, label) {
+ this.boundsOfObj(objectId, label, false)
+ },
+
+ boundsOfObj(objectId, label, outbound) {
+ let newTabName = ++this.tabIndex + '';
+ let newTab = this.addObjRefsTab(this.buildTitle(this.$t(outbound ?
+ 'jifa.heap.ref.object.outgoing' : 'jifa.heap.ref.object.incoming'), label),
+ newTabName, this.loadObjBounds, outbound)
+ newTab.loading = true
+ axios.get(heapDumpService(this.file, 'object'), {
+ params: {
+ objectId: objectId
+ }
+ }).then((resp) => {
+ let topItems = [];
+ let d = resp.data
+ topItems.push(
+ {
+ rowKey: rowKey++,
+ icon: outbound ? getOutboundIcon(d.gCRoot, d.objectType) : getIcon(d.gCRoot, d.objectType),
+ label: d.label,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ hasChildren: true,
+ objectId: d.objectId,
+ isResult: true
+ }
+ )
+ newTab.topItems = topItems
+ newTab.loading = false
+ }
+ )
+ },
+
+ addObjRefsTab(title, name, load, outbound) {
+ this.tabIndex++;
+ let newTab = {
+ title: title,
+ name: name,
+ loading: false,
+ topItems: [],
+ load: load,
+ outbound: outbound,
+ isObjRefsTab: true
+ }
+ this.editableTabs.push(newTab)
+ this.editableTabsValue = name;
+ return newTab
+ },
+
+ loadClassBounds(tree, treeNode, resolve) {
+ this.fetchClassBounds(tree.rowKey, tree.objectIds, 1, resolve)
+ },
+
+ fetchClassBounds(parentRowKey, objectIds, page, resolve) {
+ let index = this.currentIndex()
+ let tab = this.editableTabs[index]
+ let outbound = tab.outbound
+ let table = this.$refs.resultContainer[index]
+ tab.loading = true
+ axios.get(heapDumpService(this.file, outbound ? 'classReference/outbounds/children' : 'classReference/inbounds/children'), {
+ params: {
+ objectIds: JSON.stringify(objectIds),
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = table.store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(record => {
+ loaded.push({
+ rowKey: rowKey++,
+ label: record.label,
+ hasChildren: true,
+ objectId: record.objectId,
+ objectIds: record.objectIds,
+ objects: record.objects,
+ shallowHeap: record.shallowSize,
+ icon: outbound ? getClassRefOutboundIcon(record.type) : getClassRefInboundIcon(record.type),
+ isResult: true
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectIds: objectIds,
+ parentRowKey: parentRowKey,
+ isBoundsSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ tab.loading = false
+ })
+ },
+
+ outgoingRefsOfClass(objectId, label) {
+ this.boundsOfClass(objectId, label, true)
+ },
+
+ incomingRefsOfClass(objectId, label) {
+ this.boundsOfClass(objectId, label, false)
+ },
+
+ boundsOfClass(id, label, outbound) {
+ let newTabName = ++this.tabIndex + '';
+ let newTab = this.addClassRefsTab(this.buildTitle(this.$t(outbound ?
+ 'jifa.heap.ref.type.outgoing' : 'jifa.heap.ref.type.incoming'), label),
+ newTabName, this.loadClassBounds, outbound)
+ newTab.loading = true
+ axios.get(heapDumpService(this.file, outbound ? 'classReference/outbounds/class' : 'classReference/inbounds/class'), {
+ params: {
+ objectId: id,
+ }
+ }).then((resp) => {
+ let topItems = [];
+ let record = resp.data
+ topItems.push(
+ {
+ rowKey: rowKey++,
+ label: record.label,
+ hasChildren: true,
+ objectId: record.objectId,
+ objectIds: record.objectIds,
+ objects: record.objects,
+ shallowHeap: record.shallowSize,
+ icon: outbound ? getClassRefOutboundIcon(record.type) : ICONS.objects.class,
+ isResult: true
+ }
+ )
+ newTab.topItems = topItems
+ newTab.loading = false
+ }
+ )
+ },
+
+ addClassRefsTab(title, name, load, outbound) {
+ this.tabIndex++;
+ let newTab = {
+ title: title,
+ name: name,
+ loading: false,
+ topItems: [],
+ load: load,
+ outbound: outbound,
+ isClassRefsTab: true
+ }
+ this.editableTabs.push(newTab)
+ this.editableTabsValue = name;
+ return newTab
+ },
+
+ pathToGCRootsOfObj(objectId, label) {
+ let newTabName = ++this.tabIndex + '';
+ this.loadMorePathToGCRootsOfObj(this.addPathToGCRootsTab(this.buildTitle(this.$t('jifa.heap.pathToGCRoots'), label),
+ newTabName, objectId))
+ },
+
+ loadMorePathToGCRootsOfObj(tab) {
+ tab.loading = true
+ axios.get(heapDumpService(this.file, 'pathToGCRoots'), {
+ params: {
+ skip: tab.count,
+ origin: tab.origin,
+ count: 10
+ }
+ }).then((resp) => {
+ tab.count += resp.data.count
+ tab.hasMore = resp.data.hasMore
+ if (tab.treeData.length === 0) {
+ // first
+ tab.treeData.push(resp.data.tree)
+ } else {
+ this.mergePath(resp.data.tree.children, tab.treeData[0])
+ }
+ tab.loading = false
+ })
+ },
+
+ mergePath(children, parent) {
+ for (let i = 0; i < children.length; i++) {
+ let found = false
+ let child = children[i]
+ for (let j = 0; j < parent.children.length; j++) {
+ let oldChild = parent.children[j]
+ if (oldChild.objectId === child.objectId) {
+ found = true
+ this.mergePath(child.children, oldChild)
+ break;
+ }
+ }
+
+ if (!found) {
+ parent.children.push(child)
+ }
+ }
+ },
+
+ addPathToGCRootsTab(title, name, objectId) {
+ this.tabIndex++;
+ let newTab = {
+ title: title,
+ name: name,
+ loading: false,
+ isPathToGCRootsTab: true,
+ origin: objectId,
+ treeData: [],
+ hasMore: false,
+ count: 0,
+ }
+ this.editableTabs.push(newTab)
+ this.editableTabsValue = name;
+ return newTab
+ },
+
+ removeTab(targetName) {
+ let tabs = this.editableTabs;
+ let activeName = this.editableTabsValue;
+ if (activeName === targetName) {
+ tabs.forEach((tab, index) => {
+ if (tab.name === targetName) {
+ let nextTab = tabs[index + 1] || tabs[index - 1];
+ if (nextTab) {
+ activeName = nextTab.name;
+ }
+ }
+ });
+ }
+
+ this.editableTabsValue = activeName;
+ this.editableTabs = tabs.filter(tab => tab.name !== targetName);
+ }
+ },
+ watch: {
+ editableTabs() {
+ if (this.editableTabs.length === 0) {
+ this.$emit('disableShowDynamicResultSlot')
+ }
+ }
+ }
+ }
+</script>
+
+<style scoped>
+ .custom-tree-node {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 14px;
+ padding-right: 8px;
+ }
+</style>
+
+<style>
+ .resultDiv {
+ height: 100%;
+ position: relative
+ }
+</style>
diff --git a/frontend/src/components/heapdump/Fields.vue b/frontend/src/components/heapdump/Fields.vue
new file mode 100644
index 0000000..8dfd98c
--- /dev/null
+++ b/frontend/src/components/heapdump/Fields.vue
@@ -0,0 +1,173 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <el-table
+ ref="fieldsTable"
+ v-loading="loading"
+ :data="tableData"
+ :span-method="spanMethod"
+ show-header
+ highlight-current-row
+ stripe
+ :cell-style='cellStyle'
+ :header-cell-style="headerCellStyle"
+ height="100%"
+ empty-text=" "
+ >
+ <el-table-column show-overflow-tooltip label="Type" width="70px">
+ <template slot-scope="scope">
+ <p style="font-size: 12px; margin: 0 auto;" v-if="!scope.row.isSummaryItem">
+ {{scope.row.type}}
+ </p>
+ <span v-if="scope.row.isSummaryItem">
+ <img :src="ICONS.misc.sumIcon" v-if="fields.length >= totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchNextPage" style="cursor: pointer" v-else/>
+ {{ fields.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column show-overflow-tooltip label="Name" width="120px" align="center">
+ <template slot-scope="scope">
+ <p style="font-size: 12px; margin: 0 auto;">
+ {{ scope.row.name}}
+ </p>
+ </template>
+ </el-table-column>
+
+ <el-table-column show-overflow-tooltip
+ label="Value" width="500px">
+ <template slot-scope="scope">
+ <p style="font-size: 12px; margin: 0 auto;">
+ {{ scope.row.value}}
+ </p>
+ </template>
+ </el-table-column>
+ </el-table>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import {ICONS} from "./IconHealper";
+
+ export default {
+ props: {
+ file: String,
+ objectId: Number,
+ static: {type: Boolean, default: false},
+ },
+ data() {
+ return {
+ ICONS,
+ loading: false,
+ fields: [],
+ tableData: [],
+ pageSize: 25,
+ nextPage: 0,
+ totalSize: 0,
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ }
+ },
+ methods: {
+ spanMethod({row}) {
+ if (row.isSummaryItem) {
+ return [1, 3]
+ }
+ return [1, 1]
+ },
+ convert(fieldType) {
+ switch (fieldType) {
+ case 2 :
+ return 'ref'
+ case 4 :
+ return 'boolean'
+ case 5 :
+ return 'char'
+ case 6:
+ return 'float'
+ case 7:
+ return 'double'
+ case 8:
+ return 'byte'
+ case 9:
+ return 'short'
+ case 10:
+ return 'int'
+ case 11:
+ return 'long'
+ }
+ return 'unknown'
+ },
+ fetchNextPage() {
+ this.fetchFields()
+ },
+ fetchFields() {
+ if (!this.objectId) {
+ return
+ }
+ this.loading = true
+ let url = heapDumpService(this.file, this.static ? 'inspector/staticFields' : 'inspector/fields')
+ axios.get(url, {
+ params: {
+ objectId: this.objectId,
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ this.totalSize = resp.data.totalSize
+ if (this.totalSize > 0) {
+ let res = resp.data.data
+ res.forEach(f => {
+ this.fields.push({
+ type: this.convert(f.fieldType),
+ name: f.name,
+ value: f.fieldType === 2 && !f.value ? 'null' : f.value
+ })
+ }
+ )
+
+ this.tableData = this.fields.concat({
+ isSummaryItem: true
+ })
+
+ this.nextPage++;
+ this.loading = false
+ } else {
+ this.clear()
+ this.loading = false
+ }
+ })
+ },
+ clear() {
+ this.fields = []
+ this.tableData = []
+ this.totalSize = 0
+ },
+ },
+ watch: {
+ objectId(id) {
+ this.nextPage = 1
+ this.clear()
+ if (id >= 0) {
+ this.fetchFields()
+ }
+ }
+ },
+ mounted() {
+ this.nextPage = 1
+ this.clear()
+ this.fetchFields()
+ }
+ }
+</script>
diff --git a/frontend/src/components/heapdump/GCRoots.vue b/frontend/src/components/heapdump/GCRoots.vue
new file mode 100644
index 0000000..69c0095
--- /dev/null
+++ b/frontend/src/components/heapdump/GCRoots.vue
@@ -0,0 +1,341 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <el-table
+ ref="table"
+ :data="roots"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ :span-method="spanMethod"
+ row-key="rowKey"
+ lazy
+ v-loading="loading"
+ height="100%"
+ :indent=8
+ :load="load"
+ >
+
+ <el-table-column label="Class Name" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRoot">
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ {{ scope.row.label }}
+ </span>
+
+ <span v-if="scope.row.isClass" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ {{ scope.row.label }}
+ </span>
+
+ <span v-if="scope.row.isObject" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ {{ scope.row.label }}
+ <!--<span style="font-weight: bold; color: #909399">-->
+ <!--{{ scope.row.suffix }}-->
+ <!--</span>-->
+ </span>
+
+ <span v-if="scope.row.isOutbound" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ <strong>{{ scope.row.prefix }}</strong>
+ {{ scope.row.label }}
+ <span style="font-weight: bold; color: #909399">
+ {{ scope.row.suffix }}
+ </span>
+ </span>
+
+
+ <span v-if="scope.row.isClassSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchClasses(scope.row.parentRowKey, scope.row.rootTypeIndex, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer" v-else/>
+ {{ scope.row.currentSize}} <strong> / </strong> {{scope.row.totalSize}}
+ </span>
+
+ <span v-if="scope.row.isObjectSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchObjects(scope.row.parentRowKey, scope.row.rootTypeIndex,
+ scope.row.classIndex, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer" v-else/>
+ {{ scope.row.currentSize}} <strong> / </strong> {{scope.row.totalSize}}
+ </span>
+
+ <span v-if="scope.row.isOutboundsSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchOutbounds(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column label="Objects" prop="objects">
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+
+ <el-table-column label="Retained Heap" prop="retainedHeap">
+ </el-table-column>
+ </el-table>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {getIcon, getOutboundIcon, ICONS} from "./IconHealper";
+ import {heapDumpService} from '../../util'
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ data() {
+ return {
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ ICONS,
+ pageSize: 25,
+ loading: false,
+ roots: []
+ }
+ },
+
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 7]
+ } else if (index >= 1 && index <= 6) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ fetchRoots() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'GCRoots')).then(resp => {
+ let rootIndex = 0
+ resp.data.forEach(
+ root => {
+ this.roots.push({
+ rowKey: rowKey++,
+ isRoot: true,
+ rootTypeIndex: rootIndex++,
+ label: root.className,
+ objects: root.objects,
+ icon: ICONS.roots,
+ hasChildren: root.objects > 0,
+ })
+ },
+ this.loading = false
+ )
+ })
+ },
+ fetchClasses(parentRowKey, rootTypeIndex, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'GCRoots/classes'), {
+ params: {
+ rootTypeIndex: rootTypeIndex,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['table'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ let classIndex = loadedLen
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ icon: ICONS.objects.class,
+ label: d.className,
+ objects: d.objects,
+ objectId: d.objectId,
+ rootTypeIndex: rootTypeIndex,
+ classIndex: classIndex++,
+ isClass: true,
+ hasChildren: true,
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ parentRowKey: parentRowKey,
+ isClassSummary: true,
+ rootTypeIndex: rootTypeIndex,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+
+ fetchObjects(parentRowKey, rootTypeIndex, classIndex, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'GCRoots/class/objects'), {
+ params: {
+ rootTypeIndex: rootTypeIndex,
+ classIndex: classIndex,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['table'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ icon: getIcon(d.gCRoot, d.objectType),
+ label: d.label,
+ objectId: d.objectId,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ isObject: true,
+ hasChildren: true,
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ parentRowKey: parentRowKey,
+ isObjectSummary: true,
+ rootTypeIndex: rootTypeIndex,
+ classIndex: classIndex,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+
+ fetchOutbounds(parentRowKey, objectId, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'outbounds'), {
+ params: {
+ objectId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['table'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ icon: getOutboundIcon(d.gCRoot, d.objectType),
+ prefix: d.prefix,
+ label: d.label,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ hasChildren: d.hasOutbound,
+ objectId: d.objectId,
+ isOutbound: true
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isOutboundsSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+
+ load(tree, treeNode, resolve) {
+ if (tree.isRoot) {
+ this.fetchClasses(tree.rowKey, tree.rootTypeIndex, 1, resolve)
+ } else if (tree.isClass) {
+ this.fetchObjects(tree.rowKey, tree.rootTypeIndex, tree.classIndex, 1, resolve)
+ } else {
+ this.fetchOutbounds(tree.rowKey, tree.objectId, 1, resolve)
+ }
+ }
+ },
+
+ created() {
+ this.fetchRoots()
+ }
+ }
+</script>
diff --git a/frontend/src/components/heapdump/HeapDump.vue b/frontend/src/components/heapdump/HeapDump.vue
new file mode 100644
index 0000000..e0ad454
--- /dev/null
+++ b/frontend/src/components/heapdump/HeapDump.vue
@@ -0,0 +1,478 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<!--suppress HtmlUnknownTag -->
+<template>
+ <el-container style="height: 100%">
+ <el-header>
+ <view-menu subject="analysisResult"
+ :file="file" :analysisState="analysisState" :type="type" :showInspector="showInspector"
+ @setShowInspector="setShowInspector"
+ @expandResultDivWidth="expandResultDivWidth"
+ @shrinkResultDivWidth="shrinkResultDivWidth"
+ @resetResultDivWidth="resetResultDivWidth"/>
+ </el-header>
+
+ <el-main style="padding-top: 0; padding-bottom: 0; height: 100%">
+
+ <el-dialog
+ :title="$t('jifa.options')"
+ width="30%"
+ :visible.sync="optionViewVisible"
+ :close-on-press-escape=false :close-on-click-modal=false :show-close=false
+ append-to-body
+ modal>
+ <div>
+ <div>
+ <el-checkbox v-model="options.keepUnreachableObjects">Keep unreachable objects</el-checkbox>
+ </div>
+ </div>
+
+ <span slot="footer" class="dialog-footer">
+ <el-button @click="analyzeHeapDump" round>{{$t('jifa.confirm')}}</el-button>
+ </span>
+ </el-dialog>
+
+ <div style="padding-top: 20px" v-if="analysisState === 'IN_PROGRESS' || analysisState === 'ERROR'">
+ <b-progress height="2rem" show-progress :precision="2"
+ :value="progress"
+ :variant="progressState"
+ striped
+ :animated="progress < 100"/>
+ <b-card class="mt-3" bg-variant="dark" text-variant="white" v-if="message">
+ <b-card-text style="white-space: pre-line;">{{message}}</b-card-text>
+ <div class="d-flex justify-content-center mb-3" v-if="progressState === 'info'">
+ <b-spinner/>
+ </div>
+ </b-card>
+ </div>
+
+ <el-container v-if="analysisState === 'SUCCESS'" style="height: 100%">
+ <el-main style="padding: 5px; height: 100%">
+ <el-row :gutter="5" style="height: 100%">
+ <el-col :span="showInspector ? 19 : 24" style="height: 100%">
+ <el-tabs class="mainTabs" v-model="activeTab" tab-position="left" :before-leave="switchTab">
+ <el-tab-pane name="overview">
+ <span slot="label">{{$t('jifa.heap.overview')}}</span>
+ <overview :file="file"
+ @setGenerationInfoAvailable="setGenerationInfoAvailable"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"
+ />
+ </el-tab-pane>
+
+ <el-tab-pane name="leakSuspects" lazy>
+ <span slot="label">{{$t('jifa.heap.leakSuspects')}}</span>
+ <leak-suspects :file="file"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </el-tab-pane>
+
+ <el-tab-pane name="GCRoots" lazy>
+ <span slot="label">{{$t('jifa.heap.GCRoots')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <GCRoots :file="file"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="dominatorTree" lazy>
+ <span slot="label"> {{$t('jifa.heap.dominatorTree')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <dominator-tree :file="file"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="histogram" lazy>
+ <span slot="label"> {{$t('jifa.heap.histogram')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <histogram :file="file" :generationInfoAvailable="generationInfoAvailable"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="unreachableObjects" lazy>
+ <span slot="label"> {{$t('jifa.heap.unreachableObjects')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <unreachable-objects :file="file"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+
+ <el-tab-pane name="duplicatedClasses" lazy>
+ <span slot="label"> {{$t('jifa.heap.duplicatedClasses')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <duplicated-classes :file="file"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="classLoaders" lazy>
+ <span slot="label"> {{$t('jifa.heap.classLoaders')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <class-loaders :file="file"
+ @setSelectedObjectId="setSelectedObjectId"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="directByteBuffer" lazy>
+ <span slot="label"> {{$t('jifa.heap.directByteBuffer')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <direct-byte-buffer :file="file"
+ @setSelectedObjectId="setSelectedObjectId"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="systemProperty" lazy>
+ <span slot="label"> {{$t('jifa.heap.systemProperty')}}</span>
+ <system-property :file="file"/>
+ </el-tab-pane>
+
+ <el-tab-pane name="thread" lazy>
+ <span slot="label"> {{$t('jifa.heap.threadInfo')}}</span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <thread :file="file" @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="OQL" lazy>
+ <span slot="label"> OQL </span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <OQL :file="file"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"/>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane name="HeapFileCompare" lazy v-if="$jifa.dev()">
+ <span slot="label">{{ $t("jifa.heap.compare") }}</span>
+ <heap-file-compare :file="file"/>
+ </el-tab-pane>
+
+ <el-tab-pane name="dynamicResultSlot" :disabled="!showDynamicResultSlot" class="dynamicTab">
+ <span slot="label"> <i class="el-icon-more-outline"/> </span>
+ <div v-bind:style="{ 'height': '100%', 'width': resultDivWidth}">
+ <dynamic-result-slot ref="dynamicResultSlot" :file="file"
+ @disableShowDynamicResultSlot="disableShowDynamicResultSlot"
+ @setSelectedObjectId="setSelectedObjectId"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @incomingRefsOfObj="incomingRefsOfObj"
+ @outgoingRefsOfClass="outgoingRefsOfClass"
+ @incomingRefsOfClass="incomingRefsOfClass"
+ @pathToGCRootsOfObj="pathToGCRootsOfObj"/>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+ </el-col>
+
+ <el-col :span="showInspector ? 5 : 0" style="height: 100%">
+ <Inspector :file="file"
+ :objectId="selectedObjectId"
+ @outgoingRefsOfObj="outgoingRefsOfObj"
+ @setSelectedObjectId="setSelectedObjectId"
+ v-if="showInspector"/>
+ </el-col>
+ </el-row>
+ </el-main>
+ </el-container>
+ </el-main>
+ <el-footer>
+ <Footer/>
+ </el-footer>
+ </el-container>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import Footer from "../footer"
+
+ import Overview from './Overview'
+ import Inspector from './Inspector'
+ import LeakSuspects from './LeakSuspects'
+ import ViewMenu from "../menu/ViewMenu"
+ import SystemProperty from "./SystemProperty"
+ import Thread from "./Thread";
+ import Histogram from "./Histogram"
+ import DuplicatedClasses from "./DuplicatedClasses"
+ import OQL from "./OQL"
+ import DynamicResultSlot from "./DynamicResultSlot"
+ import DominatorTree from "./DominatorTree"
+ import GCRoots from "./GCRoots"
+ import UnreachableObjects from './UnreachableObjects'
+ import ClassLoaders from './ClassLoaders'
+ import DirectByteBuffer from './DirectByteBuffer'
+ import HeapFileCompare from './HeapFileCompare'
+
+ export default {
+ props: ['file'],
+ data() {
+ return {
+ type: 'HEAP_DUMP',
+ optionViewVisible: false,
+ options: {
+ keepUnreachableObjects: true,
+ },
+ progress: 0,
+ progressState: 'info',
+ message: '',
+
+ pollingInternal: 1000,
+ analysisState: 'NOT_STARTED',
+
+ activeTab: 'overview',
+ oriActiveTab: null,
+ generationInfoAvailable: false,
+ selectedObjectId: null,
+ showDynamicResultSlot: false,
+
+ showInspector: true,
+
+ resultDivWidth: '100%'
+ }
+ },
+ components: {
+ ViewMenu,
+ Inspector,
+ Overview,
+ LeakSuspects,
+ GCRoots,
+ DominatorTree,
+ DuplicatedClasses,
+ Histogram,
+ Thread,
+ SystemProperty,
+ OQL,
+ DynamicResultSlot,
+ UnreachableObjects,
+ ClassLoaders,
+ DirectByteBuffer,
+ HeapFileCompare,
+ Footer
+ },
+ methods: {
+ expandResultDivWidth() {
+ let width = parseInt(this.resultDivWidth.substr(0, this.resultDivWidth.length - 1));
+ width += 7;
+ this.resultDivWidth = width + "%";
+ },
+
+ shrinkResultDivWidth() {
+ let width = parseInt(this.resultDivWidth.substr(0, this.resultDivWidth.length - 1));
+ if (width === 100) {
+ return;
+ }
+ width -= 7;
+ this.resultDivWidth = width + "%";
+ },
+
+ resetResultDivWidth() {
+ this.resultDivWidth = '100%';
+ },
+
+ switchTab(active, old) {
+ if (old !== 'dynamicResultSlot') {
+ this.oriActiveTab = old;
+ }
+ },
+
+ setGenerationInfoAvailable(ava) {
+ this.generationInfoAvailable = ava;
+ },
+
+ setShowDynamicResultSlot(val) {
+ this.showDynamicResultSlot = val;
+ if (val) {
+ this.oriActiveTab = this.activeTab;
+ this.activeTab = 'dynamicResultSlot';
+ } else if (this.activeTab === 'dynamicResultSlot') {
+ if (!this.oriActiveTab) {
+ this.oriActiveTab = 'overview';
+ }
+ this.activeTab = this.oriActiveTab;
+ }
+ },
+
+ enableShowDynamicResultSlot() {
+ this.setShowDynamicResultSlot(true);
+ },
+
+ disableShowDynamicResultSlot() {
+ this.setShowDynamicResultSlot(false);
+ },
+
+ setSelectedObjectId(id) {
+ this.selectedObjectId = id;
+ },
+
+ setShowInspector(val) {
+ this.showInspector = val;
+ },
+
+ outgoingRefsOfObj(id, label) {
+ this.$refs['dynamicResultSlot'].outgoingRefsOfObj(id, label);
+ this.enableShowDynamicResultSlot();
+ },
+
+ incomingRefsOfObj(id, label) {
+ this.$refs['dynamicResultSlot'].incomingRefsOfObj(id, label);
+ this.enableShowDynamicResultSlot();
+ },
+
+ outgoingRefsOfClass(id, label) {
+ this.$refs['dynamicResultSlot'].outgoingRefsOfClass(id, label);
+ this.enableShowDynamicResultSlot();
+ },
+
+ incomingRefsOfClass(id, label) {
+ this.$refs['dynamicResultSlot'].incomingRefsOfClass(id, label);
+ this.enableShowDynamicResultSlot();
+ },
+
+ pathToGCRootsOfObj(id, label) {
+ this.$refs['dynamicResultSlot'].pathToGCRootsOfObj(id, label);
+ this.enableShowDynamicResultSlot();
+ },
+
+ pollProgressOfAnalysis() {
+ let self = this;
+ if (!self || self._isDestroyed) {
+ return;
+ }
+ axios.get(heapDumpService(this.file, 'progressOfAnalysis')).then(resp => {
+ let state = resp.data.state;
+ let percent = resp.data.percent;
+ if (resp.data.message) {
+ this.message = resp.data.message.replace(/\\n/gm, "<b/>");
+ }
+ if (state === 'IN_PROGRESS') {
+ if (percent >= 1) {
+ this.progress = 99;
+ } else {
+ this.progress = percent * 100;
+ }
+ setTimeout(this.pollProgressOfAnalysis, this.pollingInternal)
+ } else if (state === 'SUCCESS') {
+ this.progress = 100;
+ this.progressState = 'success';
+ this.$notify({
+ title: this.$t("jifa.goToOverViewPrompt"),
+ position: 'top-right',
+ type: "success",
+ offset: 300,
+ duration: 1000,
+ showClose: true,
+ onClose: () => {
+ this.analysisState = "SUCCESS";
+ }
+ })
+ } else {
+ this.progressState = 'danger';
+ this.analysisState = "ERROR";
+ axios.post(heapDumpService(this.file, 'release'));
+ }
+ })
+ },
+
+ analyzeHeapDump() {
+ this.optionViewVisible = false;
+ let params = new FormData();
+ params.append('keep_unreachable_objects', this.options.keepUnreachableObjects);
+ this.doAnalyzeHeapDump(params);
+ },
+
+ doAnalyzeHeapDump(params) {
+ axios.post(heapDumpService(this.file, 'analyze'), new URLSearchParams(params)).then(() => {
+ this.analysisState = "IN_PROGRESS";
+ this.pollProgressOfAnalysis();
+ })
+ },
+ },
+ mounted() {
+ axios.get(heapDumpService(this.file, 'isFirstAnalysis')).then(resp => {
+ if (resp.data.result) {
+ this.optionViewVisible = true
+ } else {
+ this.doAnalyzeHeapDump(new FormData())
+ }
+ })
+ }
+ }
+</script>
+
+<style scoped>
+ .mainTabs {
+ height: 100%;
+ }
+
+ .mainTabs /deep/ .el-tabs__content {
+ height: 100%;
+ overflow: scroll;
+ }
+
+ .mainTabs /deep/ .el-tab-pane {
+ height: 100%;
+ overflow: scroll;
+ }
+
+ .mainTabs .dynamicTab /deep/ .el-tabs__content {
+ height: unset;
+ position: absolute;
+ top: 60px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+
+ .mainTabs .dynamicTab /deep/ .el-tab-pane {
+ height: unset;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+</style>
diff --git a/frontend/src/components/heapdump/HeapFileCompare.vue b/frontend/src/components/heapdump/HeapFileCompare.vue
new file mode 100644
index 0000000..f19600b
--- /dev/null
+++ b/frontend/src/components/heapdump/HeapFileCompare.vue
@@ -0,0 +1,230 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <div style="height: 100%; position: relative">
+ <div v-if="!selectedFile" style="height: 100%">
+ <div style="height: 40px; margin-bottom: 5px; margin-top: 10px;">
+ <el-input style="margin-bottom: 10px;" size="mini" v-model="searchInput"
+ @keyup.enter.native="doSearch"
+ :placeholder="$t('jifa.typeKeyWord')" clearable/>
+ </div>
+ <div style="position: absolute; top: 50px; left: 0; right: 0; bottom: 80px;">
+ <el-table :data="candidateFiles"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='fileViewCellStyle'
+ row-key="rowKey"
+ lazy
+ height="100%"
+ v-loading="fileViewLoading"
+ >
+ <el-table-column label="File Name ( Please double click to choose a file as a heap baseline )" prop="name"
+ show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span style="cursor: pointer" @dblclick="doCompare(scope.row.finalName)">
+ <i class="el-icon-document"></i> {{scope.row.originalName}}
+ </span>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
+ <div style="position: absolute; left: 0; right: 0; bottom: 0; height: 80px">
+ <el-row type="flex" justify="space-around" style="margin-top: 15px">
+ <el-col :span="8">
+ <el-pagination
+ background
+ layout="prev, pager, next"
+ :current-page="fileViewPage"
+ :page-size="pageSize"
+ :total="candidateFileTotalSize"
+ @current-change="handleFileViewCurrentChange"
+ :hide-on-single-page=false
+ align="center">
+ </el-pagination>
+ </el-col>
+ </el-row>
+ </div>
+ </div>
+
+ <div v-else style="height: 100%">
+ <div style="margin-bottom: 6px; height: 50px">
+ <el-button size="mini" icon="el-icon-back" @click="reselect" circle></el-button>
+ <span style='margin-left: 10px; font-size: 15px; font-weight: normal;
+ font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
+ color: #606266;
+ '>
+ <i class="el-icon-document"></i> {{selectedFile}}
+ </span>
+ </div>
+
+ <div style="position: absolute; top: 50px; left: 0; right: 0; bottom: 0;">
+ <el-table :data="tableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :indent=8
+ height="100%"
+ v-loading="loading"
+ >
+ <el-table-column label="Class Name" width="800px" show-overflow-tooltip="">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRecord">
+ <img :src="classIcon"/> {{scope.row.className}}
+ </span>
+ <span v-if="scope.row.isSummary">
+ <img :src="sumIcon" v-if="records.length >= summary.totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchRecords" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{summary.totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="Objects">
+ <template slot-scope="scope">
+ {{ scope.row.objects > 0 ? '+' : '' }} {{ scope.row.objects}}
+ </template>
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap">
+ <template slot-scope="scope">
+ {{ scope.row.shallowHeap> 0 ? '+' : '' }} {{ scope.row.shallowHeap}}
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ methods: {
+ fetchCompareSummary() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'compare/summary'), {
+ params: {
+ baseline: this.selectedFile
+ }
+ }).then(resp => {
+ this.summary = resp.data
+ if (this.summary.totalSize > 0) {
+ this.fetchRecords()
+ } else {
+ this.loading = false
+ }
+ })
+ },
+ fetchRecords() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'compare/records'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ baseline: this.selectedFile
+ }
+ }).then(resp => {
+ let records = resp.data.data
+ records.forEach(record => this.records.push({
+ rowKey: rowKey++,
+ className: record.className,
+ objects: record.objects,
+ shallowHeap: record.shallowSize,
+ isRecord: true,
+ }))
+
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ objects: this.summary.objects,
+ shallowHeap: this.summary.shallowSize,
+ isSummary: true
+ })
+
+ this.nextPage++
+ this.loading = false
+ })
+ },
+ doCompare(fileName) {
+ this.selectedFile = fileName
+ this.fetchCompareSummary()
+ },
+ reselect() {
+ this.selectedFile = null
+ this.summary = null
+ this.records = []
+ this.tableData = []
+ this.nextPage = 1
+ },
+ doSearch() {
+ this.expectedFile = this.searchInput
+ this.fileViewPage = 1
+ this.fetchFiles(this.fileViewPage)
+ },
+ handleFileViewCurrentChange(page) {
+ this.fetchFiles(page)
+ },
+ fetchFiles(page) {
+ this.fileViewLoading = true
+ axios.get(heapDumpService(this.file, 'compare/files'), {
+ params: {
+ page: page,
+ pageSize: this.pageSize,
+ expected: this.expectedFile,
+ }
+ }).then(resp => {
+ this.candidateFileTotalSize = resp.data.totalSize
+ this.candidateFiles = resp.data.data
+ this.fileViewLoading = false
+ })
+ }
+ },
+ data() {
+ return {
+ fileViewCellStyle: {padding: '8px', fontSize: '15px'},
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ pageSize: 25,
+
+ fileViewPage: 1,
+ fileViewLoading: false,
+ searchInput: null,
+ expectedFile: null,
+ candidateFiles: [],
+ candidateFileTotalSize: 0,
+
+
+ selectedFile: null,
+ classIcon: require('../../assets/heap/objects/class.gif'),
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ loading: false,
+ summary: null,
+ nextPage: 1,
+ records: [],
+ tableData: [],
+ }
+ },
+ created() {
+ this.fetchFiles(this.fileViewPage)
+ }
+ }
+</script>
diff --git a/frontend/src/components/heapdump/Histogram.vue b/frontend/src/components/heapdump/Histogram.vue
new file mode 100644
index 0000000..da9a607
--- /dev/null
+++ b/frontend/src/components/heapdump/Histogram.vue
@@ -0,0 +1,207 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div style="height: 100%">
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-item divider/>
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <el-table :data="tableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :span-method="spanMethod"
+ height="100%"
+ :indent=8
+ v-loading="loading"
+ >
+ <el-table-column :label="label">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRecord" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu
+ style="cursor: pointer">
+ <img :src="scope.row.icon"/> {{scope.row.label}}
+ </span>
+
+ <span v-if="scope.row.isSummary">
+ <img :src="sumIcon" v-if="records.length >= totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchHistogram" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+
+ <el-table-column v-if="generationInfoAvailable"/>
+ <el-table-column v-if="generationInfoAvailable"/>
+ <el-table-column v-if="generationInfoAvailable"/>
+
+ <el-table-column v-if="!generationInfoAvailable"/>
+ <el-table-column v-if="!generationInfoAvailable"/>
+ <el-table-column v-if="!generationInfoAvailable"/>
+ <el-table-column v-if="!generationInfoAvailable"/>
+ <el-table-column v-if="!generationInfoAvailable"/>
+
+ <el-table-column label="Objects" prop="numberOfObjects">
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap" prop="shallowSize">
+ </el-table-column>
+
+ <el-table-column label="Objects(Y)" prop="numberOfYoungObjects" v-if="generationInfoAvailable">
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap(Y) " prop="shallowSizeOfYoung" v-if="generationInfoAvailable">
+ </el-table-column>
+
+ <el-table-column label="Objects(O)" prop="numberOfOldObjects" v-if="generationInfoAvailable">
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap(O)" prop="shallowSizeOfOld" v-if="generationInfoAvailable">
+ </el-table-column>
+
+ <el-table-column label="Retained Heap">
+ <template slot-scope="scope">
+ <span v-if="scope.row.retainedSize < 0">
+ >= {{ -scope.row.retainedSize }}
+ </span>
+
+ <span v-else>
+ {{ scope.row.retainedSize }}
+ </span>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+</template>
+
+<script>
+
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ let rowKey = 1
+ export default {
+ props: ['file', 'generationInfoAvailable'],
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (this.generationInfoAvailable) {
+ if (index === 0) {
+ return [1, 4]
+ } else if (index >= 1 && index <= 3) {
+ return [0, 0]
+ }
+ return [1, 1]
+ } else {
+ if (index === 0) {
+ return [1, 6]
+ } else if (index >= 1 && index <= 5) {
+ return [0, 0]
+ }
+ return [1, 1]
+ }
+ },
+ fetchHistogram() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'histogram'), {
+ params: {
+ groupingBy: this.groupingBy,
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let records = resp.data.data
+ this.totalSize = resp.data.totalSize
+ records.forEach(record =>
+ this.records.push({
+ rowKey: rowKey++,
+ objectId: record.objectId,
+ label: record.label,
+ icon: this.classIcon,
+ numberOfObjects: record.numberOfObjects,
+ shallowSize: record.shallowSize,
+
+ numberOfYoungObjects: record.numberOfYoungObjects,
+ shallowSizeOfYoung: record.shallowSizeOfYoung,
+
+ numberOfOldObjects: record.numberOfOldObjects,
+ shallowSizeOfOld: record.shallowSizeOfOld,
+
+ retainedSize: record.retainedSize,
+ isRecord: true
+ }))
+
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ isSummary: true
+ })
+ this.nextPage++
+ this.loading = false
+ })
+ },
+ },
+ data() {
+ return {
+ loading: false,
+ classIcon: require('../../assets/heap/objects/class.gif'),
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ label: 'Class Name',
+ groupingBy: 'by_class',
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+
+ records: [],
+ tableData: [],
+ nextPage: 1,
+ pageSize: 25,
+ totalSize: 0,
+
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+ }
+ },
+ created() {
+ this.fetchHistogram()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/IconHealper.js b/frontend/src/components/heapdump/IconHealper.js
new file mode 100644
index 0000000..3e1f988
--- /dev/null
+++ b/frontend/src/components/heapdump/IconHealper.js
@@ -0,0 +1,152 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export const ICONS = {
+ id: require('../../assets/heap/id.gif'),
+ size: require('../../assets/heap/size.gif'),
+ roots: require('../../assets/heap/roots.gif'),
+ misc: {
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ },
+ decorations: {
+ gc_root: require('../../assets/heap/decorations/gc_root.gif')
+ },
+ objects: {
+ class_obj: require('../../assets/heap/objects/class_obj.gif'),
+ class_obj_gc_root: require('../../assets/heap/objects/class_obj_gc_root.gif'),
+ classloader_obj: require('../../assets/heap/objects/classloader_obj.gif'),
+ classloader_obj_gc_root: require('../../assets/heap/objects/classloader_obj_gc_root.gif'),
+ array_obj: require('../../assets/heap/objects/array_obj.gif'),
+ array_obj_gc_root: require('../../assets/heap/objects/array_obj_gc_root.gif'),
+ instance_obj: require('../../assets/heap/objects/instance_obj.gif'),
+ instance_obj_gc_root: require('../../assets/heap/objects/instance_obj_gc_root.gif'),
+ class_package: require('../../assets/heap/objects/package.gif'),
+ superclass: require('../../assets/heap/objects/superclass.gif'),
+ class: require('../../assets/heap/objects/class.gif'),
+
+ out: {
+ class_obj: require('../../assets/heap/objects/out/class_obj.gif'),
+ class: require('../../assets/heap/objects/out/class.gif'),
+ class_mixed: require('../../assets/heap/objects/out/class_mixed.gif'),
+ class_old: require('../../assets/heap/objects/out/class_out_old.gif'),
+ class_obj_gc_root: require('../../assets/heap/objects/out/class_obj_gc_root.gif'),
+ classloader_obj: require('../../assets/heap/objects/out/classloader_obj.gif'),
+ classloader_obj_gc_root: require('../../assets/heap/objects/out/classloader_obj_gc_root.gif'),
+ array_obj: require('../../assets/heap/objects/out/array_obj.gif'),
+ array_obj_gc_root: require('../../assets/heap/objects/out/array_obj_gc_root.gif'),
+ instance_obj: require('../../assets/heap/objects/out/instance_obj.gif'),
+ instance_obj_gc_root: require('../../assets/heap/objects/out/instance_obj_gc_root.gif'),
+ },
+
+ in: {
+ class_obj: require('../../assets/heap/objects/in/class_obj.gif'),
+ class: require('../../assets/heap/objects/in/class.gif'),
+ class_mixed: require('../../assets/heap/objects/in/class_mixed.gif'),
+ class_old: require('../../assets/heap/objects/in/class_in_old.gif'),
+ class_obj_gc_root: require('../../assets/heap/objects/in/class_obj_gc_root.gif'),
+ classloader_obj: require('../../assets/heap/objects/in/classloader_obj.gif'),
+ classloader_obj_gc_root: require('../../assets/heap/objects/in/classloader_obj_gc_root.gif'),
+ array_obj: require('../../assets/heap/objects/in/array_obj.gif'),
+ array_obj_gc_root: require('../../assets/heap/objects/in/array_obj_gc_root.gif'),
+ instance_obj: require('../../assets/heap/objects/in/instance_obj.gif'),
+ instance_obj_gc_root: require('../../assets/heap/objects/in/instance_obj_gc_root.gif'),
+ },
+ }
+}
+
+import {CLASS_TYPE, OBJECT_TYPE} from "./CommonType";
+
+export function getIcon(isGCRoot, objType) {
+
+ if (objType === OBJECT_TYPE.CLASS) {
+ return isGCRoot ? ICONS.objects.class_obj_gc_root : ICONS.objects.class_obj;
+ }
+
+ if (objType === OBJECT_TYPE.CLASSLOADER) {
+ return isGCRoot ? ICONS.objects.classloader_obj_gc_root : ICONS.objects.classloader_obj;
+ }
+
+ if (objType === OBJECT_TYPE.ARRAY) {
+ return isGCRoot ? ICONS.objects.array_obj_gc_root : ICONS.objects.array_obj;
+ }
+
+ if (objType === OBJECT_TYPE.NORMAL) {
+ return isGCRoot ? ICONS.objects.instance_obj_gc_root : ICONS.objects.instance_obj;
+ }
+}
+
+export function getOutboundIcon(isGCRoot, objType) {
+
+ if (objType === OBJECT_TYPE.CLASS) {
+ return isGCRoot ? ICONS.objects.out.class_obj_gc_root : ICONS.objects.out.class_obj;
+ }
+
+ if (objType === OBJECT_TYPE.CLASSLOADER) {
+ return isGCRoot ? ICONS.objects.out.classloader_obj_gc_root : ICONS.objects.out.classloader_obj;
+ }
+
+ if (objType === OBJECT_TYPE.ARRAY) {
+ return isGCRoot ? ICONS.objects.out.array_obj_gc_root : ICONS.objects.out.array_obj;
+ }
+
+ if (objType === OBJECT_TYPE.NORMAL) {
+ return isGCRoot ? ICONS.objects.out.instance_obj_gc_root : ICONS.objects.out.instance_obj;
+ }
+}
+
+export function getInboundIcon(isGCRoot, objType) {
+
+ if (objType === OBJECT_TYPE.CLASS) {
+ return isGCRoot ? ICONS.objects.in.class_obj_gc_root : ICONS.objects.in.class_obj;
+ }
+
+ if (objType === OBJECT_TYPE.CLASSLOADER) {
+ return isGCRoot ? ICONS.objects.in.classloader_obj_gc_root : ICONS.objects.in.classloader_obj;
+ }
+
+ if (objType === OBJECT_TYPE.ARRAY) {
+ return isGCRoot ? ICONS.objects.in.array_obj_gc_root : ICONS.objects.in.array_obj;
+ }
+
+ if (objType === OBJECT_TYPE.NORMAL) {
+ return isGCRoot ? ICONS.objects.in.instance_obj_gc_root : ICONS.objects.in.instance_obj;
+ }
+}
+
+export function getClassRefInboundIcon(type) {
+ if (type === CLASS_TYPE.NEW) {
+ return ICONS.objects.in.class
+ }
+
+ if (type === CLASS_TYPE.MIXED) {
+ return ICONS.objects.in.class_mixed
+
+ }
+ if (type === CLASS_TYPE.OLD_FAD) {
+ return ICONS.objects.in.class_old
+ }
+}
+
+export function getClassRefOutboundIcon(type) {
+ if (type === CLASS_TYPE.NEW) {
+ return ICONS.objects.out.class
+ }
+
+ if (type === CLASS_TYPE.MIXED) {
+ return ICONS.objects.out.class_mixed
+
+ }
+ if (type === CLASS_TYPE.OLD_FAD) {
+ return ICONS.objects.out.class_old
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/Inspector.vue b/frontend/src/components/heapdump/Inspector.vue
new file mode 100644
index 0000000..ddc4ac2
--- /dev/null
+++ b/frontend/src/components/heapdump/Inspector.vue
@@ -0,0 +1,276 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-clipboard="http://www.w3.org/1999/xhtml">
+ <el-container style="height: 100%">
+ <el-main style="padding: 0; height: 100%">
+ <div style="height: 100%; position: relative;">
+ <el-tabs class="firstTabs" value="inspectorObjectView" style="position:relative; height: 38%;">
+ <el-tab-pane name="inspectorObjectView">
+ <span slot="label">
+ <i class="el-icon-search"/>
+ <span style="margin-left: 2px"> Inspector</span>
+ </span>
+
+ <div style="margin-bottom: 5px">
+ <el-input size="mini"
+ width="60%"
+ placeholder="Object Address"
+ class="input-with-select"
+ v-model="objectAddress"
+ @keyup.enter.native="searchByAddress"
+ clearable>
+ <el-button slot="append" :icon="searching ? 'el-icon-loading' : 'el-icon-search'"
+ :disabled="searching"
+ @click="searchByAddress"/>
+ </el-input>
+ </div>
+
+
+ <el-table v-loading="viewLoading"
+ :data="objectOverview"
+ :show-header="false"
+ :highlight-current-row="true"
+ stripe
+ :cell-style="cellStyle"
+ empty-text=" "
+ height="80%"
+ >
+ <el-table-column align="left" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <p style="font-size: 12px; margin: 0 auto;">
+ <img :src="scope.row.icon"/> {{ scope.row.data}}
+ <span style="font-weight: bold; color: #909399"
+ v-if="scope.row.suffix">{{ " " + scope.row.suffix}}</span>
+ <i v-if="scope.row.copyable" class="el-icon-document-copy copy-icon"
+ style="padding-left: 5px"
+ v-clipboard:copy="scope.row.data"/>
+ </p>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+ </el-tabs>
+
+ <el-tabs :value="activeName"
+ class="bottomTabs" style="position: absolute; top: 38%; left: 0; right: 0; bottom: 0;">
+ <el-tab-pane label="Attributes" name="Attributes">
+ <Fields :file="file" :object-id="objectId"/>
+ </el-tab-pane>
+ <el-tab-pane label="Statics" name="Statics">
+ <div style="height: 100%">
+ <Fields :file="file" :object-id="objectId" static/>
+ </div>
+ </el-tab-pane>
+ <!-- <el-tab-pane label="Class Hierarchy" name="Class Hierarchy" disabled>-->
+ <!-- </el-tab-pane>-->
+ <el-tab-pane label="Value" name="Value">
+ <div v-loading="valueLoading">
+ <el-input
+ v-model="objectValue"
+ type="textarea"
+ style="font-size: 12px"
+ readonly
+ autosize>
+ </el-input>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+ </div>
+ </el-main>
+ </el-container>
+</template>
+<script>
+
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import {getIcon, ICONS} from './IconHealper';
+ import {OBJECT_TYPE} from './CommonType';
+ import Fields from './Fields'
+
+ export default {
+ components: {Fields},
+ props: ['file', 'objectId'],
+ data() {
+ return {
+ objectOverview: [],
+ activeName: 'Attributes',
+ cellStyle: {padding: 0},
+ objectValue: '',
+ objectAddress: '',
+ searching: false,
+ viewLoading: false,
+ valueLoading: false,
+ }
+ },
+ methods: {
+ locationDesc(locationType) {
+ if (locationType === 1) {
+ return "Young"
+ }
+
+ if (locationType === 2) {
+ return "Old"
+ }
+ return ""
+ },
+ searchByAddress() {
+ if (this.objectAddress) {
+ this.searching = true
+ let address = this.objectAddress
+ if (address.startsWith('0x') || address.startsWith('0X')) {
+ address = address.substring(2)
+ }
+ address = parseInt(address, 16);
+ axios.get(heapDumpService(this.file, "inspector/addressToId"), {
+ params: {
+ objectAddress: address
+ }
+ }).then(resp => {
+ this.$emit('setSelectedObjectId', resp.data)
+ this.$emit('outgoingRefsOfObj', resp.data, this.objectAddress)
+ this.searching = false
+ }).catch(() => {
+ this.objectAddress = null
+ this.searching = false
+ })
+ }
+ },
+ inspect() {
+ if (!this.objectId) {
+ return
+ }
+
+ this.viewLoading = true
+ axios.get(heapDumpService(this.file, "inspector/objectView"), {
+ params: {
+ objectId: this.objectId
+ }
+ }).then(resp => {
+ let ov = resp.data
+
+ let oa = '0x' + ov.objectAddress.toString(16)
+
+ let tmpView = []
+ tmpView.push({data: oa, icon: ICONS.id, suffix: this.locationDesc(ov.locationType), copyable: true})
+ let name = ov.name
+ let p = ''
+ let dotPos = name.lastIndexOf(".")
+ if (dotPos >= 0) {
+ p = name.substring(0, dotPos)
+ name = name.substring(dotPos + 1)
+ }
+ tmpView.push({data: name, icon: getIcon(ov.gCRoot, ov.objectType)})
+ tmpView.push({data: p, icon: ICONS.objects.class_package})
+
+ tmpView.push({
+ data: ov.classLabel,
+ icon: getIcon(ov.classGCRoot, OBJECT_TYPE.CLASS)
+ })
+
+ tmpView.push({data: ov.superClassName ? ov.superClassName : ' ', icon: ICONS.objects.superclass})
+
+ tmpView.push({
+ data: ov.classLoaderLabel,
+ icon: getIcon(ov.classLoaderGCRoot, OBJECT_TYPE.CLASSLOADER)
+ })
+ tmpView.push({data: ov.shallowSize + ' (shallow size)', icon: ICONS.size})
+ tmpView.push({data: ov.retainedSize + ' (retained size)', icon: ICONS.size})
+ tmpView.push({data: ov.gcRootInfo, icon: ICONS.decorations.gc_root})
+ this.objectOverview = tmpView
+ let maxContent = ''
+ tmpView.forEach(v => {
+ if (v.data.length > maxContent.length) {
+ maxContent = v.data
+ }
+ })
+ if (ov.objectType === OBJECT_TYPE.CLASS) {
+ this.activeName = 'Statics'
+ } else {
+ this.activeName = 'Attributes'
+ }
+ this.viewLoading = false
+ }).catch(() => {
+ this.objectOverview = []
+ this.viewLoading = false
+ })
+
+ this.valueLoading = true
+ axios.get(heapDumpService(this.file, "inspector/value"), {
+ params: {
+ objectId: this.objectId
+ }
+ }).then(resp => {
+ this.objectValue = resp.data
+ this.valueLoading = false
+ }).catch(() => {
+ this.valueLoading = false
+ })
+ },
+ },
+ watch: {
+ objectId(id) {
+ if (id >= 0) {
+ this.inspect()
+ } else {
+ this.objectOverview = []
+ }
+ },
+ },
+ mounted() {
+ this.inspect()
+ }
+ }
+</script>
+
+<style scoped>
+ .copy-icon:hover {
+ color: #409EFF;
+ cursor: pointer;
+ }
+
+ .firstTabs /deep/ .el-tabs__content {
+ position: absolute;
+ top: 45px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+
+ .firstTabs /deep/ .el-tab-pane {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+
+ .bottomTabs /deep/ .el-tabs__content {
+ position: absolute;
+ top: 45px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+
+ .bottomTabs /deep/ .el-tab-pane {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: scroll;
+ }
+</style>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/LeakSuspects.vue b/frontend/src/components/heapdump/LeakSuspects.vue
new file mode 100644
index 0000000..a5d01e5
--- /dev/null
+++ b/frontend/src/components/heapdump/LeakSuspects.vue
@@ -0,0 +1,165 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <div style="height: 100%; position: relative">
+ <el-collapse v-if="useful" v-model="activeNames" style="width: 100%">
+ <el-collapse-item v-loading="loading" :title='$t("jifa.heap.overview")' name="0">
+ <div style="position: relative;">
+ <div style="position: absolute; top: 30px; left: 30px;" v-html="descOfSelectedSlice"></div>
+ <div>
+ <doughnut-chart :chart-data="chartData" :options="chartOptions"></doughnut-chart>
+ </div>
+ </div>
+ </el-collapse-item>
+ <el-collapse-item v-for="(record) in records" v-bind:key="record.name" :title="record.name" :name="record.name">
+ <el-tabs tab-position="left">
+ <el-tab-pane :label="$t('jifa.heap.description')">
+ <div v-html="record.desc"></div>
+ </el-tab-pane>
+ <el-tab-pane v-if="record.paths" :label="$t('jifa.heap.detail')">
+ <el-tree
+ :data="record.paths"
+ node-key="objectId"
+ >
+ <span class="custom-tree-node" style="font-size: 12px" slot-scope="{ node, data }"
+ @click="$emit('setSelectedObjectId', data.objectId)">
+ <span>
+ <img :src="getIcon(data.gCRoot, data.objectType)" style="margin-right: 5px"/>
+ {{ data.label }}
+ </span>
+ <span>
+ {{ data.shallowSize }} / {{ data.retainedSize }}
+ </span>
+ </span>
+
+ </el-tree>
+ </el-tab-pane>
+ </el-tabs>
+ </el-collapse-item>
+ </el-collapse>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import DoughnutChart from '../charts/DoughnutChart'
+ import {heapDumpService} from '../../util'
+ import {a2rgb, PIE_COLORS, REMAINDER_COLOR} from "./ColorHelper";
+ import {getIcon} from "./IconHealper"
+
+ export default {
+ props: ['file'],
+ components: {
+ DoughnutChart
+ },
+ methods: {
+ getIcon,
+ clickPie(event, elements) {
+ if (elements.length > 0) {
+ let index = elements[0]._index
+ this.descOfSelectedSlice = this.slices[index].desc
+ this.$emit("setSelectedObjectId", this.slices[index].objectId)
+ } else {
+ this.descOfSelectedSlice = null
+ }
+ },
+ fetchReport() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'leak/report')).then(resp => {
+ this.useful = resp.data.useful
+ if (this.useful) {
+ this.slices = resp.data.slices
+ let labels = []
+ let data = []
+ for (let i = 0; i < this.slices.length; i++) {
+ labels.push(this.slices[i].label)
+ data.push(this.slices[i].value)
+ }
+
+ let color = []
+ let len = this.slices.length
+ for (let i = 0; i < len - 1; i++) {
+ color.push(a2rgb(PIE_COLORS[i % PIE_COLORS.length]))
+ }
+ if (this.slices[len - 1].objectId === -1
+ || this.slices[len - 1].label === 'Remainder') {
+ color.push(a2rgb(REMAINDER_COLOR))
+ } else {
+ color.push(a2rgb((len - 1) % PIE_COLORS.length))
+ }
+
+ this.chartData = {
+ labels: labels,
+ datasets: [
+ {
+ backgroundColor: color,
+ data: data,
+ }
+ ]
+ }
+
+ this.records = resp.data.records
+ this.records.forEach(
+ r => {
+ this.activeNames.push(r.name)
+ }
+ )
+ }
+ this.loading = false
+ })
+ }
+
+ },
+ data() {
+ return {
+ activeNames: ['0'],
+ loading: false,
+
+ chartData: {},
+ chartOptions: {
+ legend: false,
+ responsive: true,
+ maintainAspectRatio: false,
+ pieceLabel: {
+ mode: 'percentage',
+ precision: 1
+ },
+ animation: {
+ // animateScale: true,
+ // easing: 'linear'
+ },
+ onClick: this.clickPie
+ },
+
+ useful: true,
+ slices: null,
+ descOfSelectedSlice: null,
+ records: null,
+ }
+ },
+ created() {
+ this.fetchReport()
+ }
+ }
+</script>
+
+<style scoped>
+ .custom-tree-node {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ font-size: 14px;
+ padding-right: 8px;
+ }
+</style>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/OQL.vue b/frontend/src/components/heapdump/OQL.vue
new file mode 100644
index 0000000..54642b5
--- /dev/null
+++ b/frontend/src/components/heapdump/OQL.vue
@@ -0,0 +1,378 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div style="height: 100%; position: relative">
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ <v-contextmenu-item divider></v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('pathToGCRootsOfObj', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <div style="height: 45px; margin-top: 5px">
+ <el-autocomplete
+ v-model="oql"
+ :fetch-suggestions="queryHistory"
+ placeholder="Object Query Language ..."
+ :trigger-on-focus="false"
+ prefix-icon="el-icon-edit"
+ @keyup.enter.native="search"
+ clearable
+ style="display: flex"
+ >
+ <template slot="append">
+ <el-button :icon="searching ? 'el-icon-loading':'el-icon-search'" :disabled="searching" @click="search">
+ </el-button>
+ </template>
+ </el-autocomplete>
+ </div>
+
+ <div align="left" style="height: 25px; margin-bottom: 5px">
+ <a href="https://help.eclipse.org/oxygen/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Freference%2Foqlsyntax.html&cp=66_4_2"
+ target="_blank" style="font-size: 12px; font-weight: bold; color: #909399">
+ OQL Help
+ </a>
+ </div>
+
+ <div v-loading="loading" style="position: absolute; top: 80px; left: 0; right: 0; bottom: 0;">
+ <el-table v-if="isTreeResult"
+ ref='treeResultTable' :data="treeTableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :indent=8
+ height="100%"
+ :load="loadOutbounds">
+ <el-table-column label="Class Name" width="800px" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isResult" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.label"
+ v-contextmenu:contextmenu>
+ <img :src="scope.row.icon" style="margin-right: 5px"/>
+ <strong>{{ scope.row.prefix }}</strong>
+ {{ scope.row.label }}
+ <span style="font-weight: bold; color: #909399">
+ {{ scope.row.suffix }}
+ </span>
+ </span>
+
+ <span v-if="scope.row.isOutboundsSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchOutbounds(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+
+ <span v-if="scope.row.isSummaryItem">
+ <img :src="ICONS.misc.sumIcon" v-if="treeResult.length >= totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchResult(scope.row.oql)" style="cursor: pointer" v-else/>
+ {{ treeResult.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+ <el-table-column label="Retained Heap" prop="retainedHeap">
+ </el-table-column>
+ </el-table>
+
+ <el-table v-if="isTableResult"
+ ref='tableResultTable' :data="tableTableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :indent=8
+ height="100%">
+
+ <el-table-column v-for="(column, index) in tableResultColumns" :label="column" v-bind:key="column">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isResult" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer"
+ @contextmenu="contextMenuTargetObjectId = scope.row.objectId; contextMenuTargetObjectLabel = scope.row.values[index] ? scope.row.values[index] : 'null'"
+ v-contextmenu:contextmenu>
+ {{ scope.row.values[index] ? scope.row.values[index] : 'null' }}
+ </span>
+
+ <span v-if="scope.row.isSummaryItem && index === 0">
+ <img :src="ICONS.misc.sumIcon" v-if="tableResult.length >= totalSize"/>
+ <img :src="ICONS.misc.sumPlusIcon" @dblclick="fetchResult(scope.row.oql)" style="cursor: pointer" v-else/>
+ {{ tableResult.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+ </el-table>
+
+
+ <el-input v-if="isTextResult"
+ v-model="textResult"
+ type="textarea"
+ readonly
+ autosize>
+ </el-input>
+ </div>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {getOutboundIcon, ICONS} from "./IconHealper";
+ import {heapDumpService} from "../../util";
+
+ let rowKey = 1
+
+ // oql result type
+ const TREE = 1
+ const TABLE = 2
+ const TEXT = 3
+
+ export default {
+ props: ['file'],
+ data() {
+ return {
+ ICONS,
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+ searching: false,
+ loading: false,
+ oql: '',
+ nextPage: 1,
+ pageSize: 25,
+ totalSize: 0,
+ resultType: 0,
+
+ contextMenuTargetObjectId: null,
+ contextMenuTargetObjectLabel: null,
+
+ treeResult: [],
+ treeTableData: [],
+
+ tableResult: [],
+ tableResultColumns: [],
+ tableTableData: [],
+
+ textResult: '',
+
+ isTreeResult: false,
+ isTableResult: false,
+ isTextResult: false,
+
+ historyOQLs: []
+ }
+ },
+ methods: {
+ adjustDataByResultType(type) {
+ this.isTreeResult = type === TREE
+ this.isTableResult = type === TABLE
+ this.isTextResult = type === TEXT
+ },
+ fetchResult(oql) {
+ if (!oql || oql.length === 0) {
+ return
+ }
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'oql'), {
+ params: {
+ oql: oql,
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ this.adjustDataByResultType(resp.data.type)
+ if (this.isTreeResult) {
+ this.putHistory(oql)
+ this.totalSize = resp.data.pv.totalSize
+ let data = resp.data.pv.data
+ data.forEach(d => {
+ this.treeResult.push({
+ rowKey: rowKey++,
+ icon: getOutboundIcon(d.gCRoot, d.objectType),
+ prefix: d.prefix,
+ label: d.label,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ hasChildren: d.hasOutbound,
+ objectId: d.objectId,
+ isResult: true
+ })
+ })
+ this.treeTableData = this.treeResult.concat({
+ rowKey: rowKey++,
+ oql: oql,
+ isSummaryItem: true
+ })
+ this.nextPage++
+ } else if (this.isTableResult) {
+ this.putHistory(oql)
+ this.totalSize = resp.data.pv.totalSize
+ this.tableResultColumns = resp.data.columns
+ let data = resp.data.pv.data
+ data.forEach(d => {
+ this.tableResult.push({
+ rowKey: rowKey++,
+ objectId: d.objectId,
+ values: d.values,
+ hasChildren: false,
+ isResult: true
+ })
+ })
+ this.tableTableData = this.tableResult.concat({
+ rowKey: rowKey++,
+ oql: oql,
+ isSummaryItem: true
+ })
+ this.nextPage++
+ } else if (this.isTextResult) {
+ this.textResult = resp.data.text
+ }
+ this.searching = false
+ this.loading = false
+ })
+ },
+ loadOutbounds(tree, treeNode, resolve) {
+ this.fetchOutbounds(tree.rowKey, tree.objectId, 1, resolve)
+ },
+ fetchOutbounds(parentRowKey, objectId, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'outbounds'), {
+ params: {
+ objectId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['treeResultTable'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+
+ let res = resp.data.data
+ res.forEach(d => {
+ loaded.push({
+ rowKey: rowKey++,
+ icon: getOutboundIcon(d.gCRoot, d.objectType),
+ prefix: d.prefix,
+ label: d.label,
+ suffix: d.suffix,
+ shallowHeap: d.shallowSize,
+ retainedHeap: d.retainedSize,
+ hasChildren: d.hasOutbound,
+ objectId: d.objectId,
+ isResult: true
+ })
+ })
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isOutboundsSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+ },
+ clear() {
+ this.nextPage = 1
+ this.totalSize = 0
+
+ this.treeResult = []
+ this.treeTableData = []
+
+ this.tableResult = []
+ this.tableResultColumns = []
+ this.tableTableData = []
+ this.textResult = ''
+ },
+
+ search() {
+ if (this.oql) {
+ this.searching = true
+ this.clear()
+ this.fetchResult(this.oql)
+ }
+ },
+
+ putHistory(oql) {
+ let target = oql.trim()
+ for (let i = 0; i < this.historyOQLs.length; i++) {
+ if (this.historyOQLs[i].value === target) {
+ return
+ }
+ }
+
+ this.historyOQLs.push({value: target})
+ if (this.historyOQLs.length > 11) {
+ this.historyOQLs.shift()
+ }
+ },
+
+ queryHistory(queryString, cb) {
+ let history = this.historyOQLs;
+ let results = queryString ? history.filter(this.createFilter(queryString)) : history;
+ cb(results);
+ },
+
+ createFilter(queryString) {
+ return (history) => {
+ return (history.value.toLowerCase().indexOf(queryString.toLowerCase().trim()) === 0);
+ };
+ },
+ }
+ }
+</script>
diff --git a/frontend/src/components/heapdump/Overview.vue b/frontend/src/components/heapdump/Overview.vue
new file mode 100644
index 0000000..45c9012
--- /dev/null
+++ b/frontend/src/components/heapdump/Overview.vue
@@ -0,0 +1,210 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-contextmenu="http://www.w3.org/1999/xhtml">
+ <div>
+ <v-contextmenu ref="contextmenu">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.object.label')"
+ v-if="selectedBigObject && selectedBigObject.objectId >=0">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfObj', selectedBigObject.objectId, selectedBigObject.label)">
+ {{$t('jifa.heap.ref.object.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfObj', selectedBigObject.objectId, selectedBigObject.label)">
+ {{$t('jifa.heap.ref.object.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')"
+ v-if="this.selectedBigObject && this.selectedBigObject.objectId >=0">
+ <v-contextmenu-submenu :title="$t('jifa.heap.ref.type.label')">
+ <v-contextmenu-item
+ @click="$emit('outgoingRefsOfClass', contextMenuTargetObjectId, contextMenuTargetObjectLabel)">
+ {{$t('jifa.heap.ref.type.outgoing')}}
+ </v-contextmenu-item>
+ <v-contextmenu-item
+ @click="$emit('incomingRefsOfClass', selectedBigObject.objectId, selectedBigObject.label())">
+ {{$t('jifa.heap.ref.type.incoming')}}
+ </v-contextmenu-item>
+ </v-contextmenu-submenu>
+ </v-contextmenu-submenu>
+
+ <v-contextmenu-item divider v-if="selectedBigObject && selectedBigObject.objectId >=0"></v-contextmenu-item>
+
+ <v-contextmenu-item
+ v-if="selectedBigObject && selectedBigObject.objectId >=0"
+ @click="$emit('pathToGCRootsOfObj', selectedBigObject.objectId, selectedBigObject.label)">
+ {{$t('jifa.heap.pathToGCRoots')}}
+ </v-contextmenu-item>
+ </v-contextmenu>
+
+ <el-collapse v-model="activeNames" style="width: 100%;">
+ <el-collapse-item v-loading="loading" :title="$t('jifa.heap.basicInformation')" name="1">
+ <el-table v-loading="loading"
+ :data="details"
+ :show-header="false"
+ :highlight-current-row="false"
+ stripe
+ :cell-style='cellStyle'
+ height="280px"
+ >
+ <el-table-column prop="key" width="300px">
+ </el-table-column>
+ <el-table-column prop="value">
+ </el-table-column>
+ </el-table>
+ </el-collapse-item>
+
+ <el-collapse-item v-loading="loading" title='Biggest Objects by Retained Size' name="2">
+ <doughnut-chart :chart-data="chartData" :options="chartOptions" v-contextmenu:contextmenu></doughnut-chart>
+ <p style='margin-top: 20px; margin-bottom: -20px; font-size: 13px; font-weight: 500; color: #606266;'>
+ {{selectedBigObject ? buildSelectedBigObjectInfo() : $t("jifa.heap.usedHeapSize") + ': '
+ +toSizeString(totalSize)}}
+ </p>
+ </el-collapse-item>
+ </el-collapse>
+ </div>
+</template>
+<script>
+ import DoughnutChart from '../charts/DoughnutChart'
+ import axios from 'axios'
+ import {heapDumpService, toCountString, toSizeString} from '../../util'
+ import {formatDate} from 'element-ui/src/utils/date-util'
+ import {a2rgb, PIE_COLORS, REMAINDER_COLOR} from "./ColorHelper";
+
+ export default {
+ props: ['file'],
+ components: {
+ DoughnutChart
+ },
+ methods: {
+ toSizeString,
+ selectBigObject(event, elements) {
+ if (elements.length > 0) {
+ let index = elements[0]._index
+ this.selectedBigObject = this.bigObjects[index]
+ this.$emit("setSelectedObjectId", this.selectedBigObject.objectId)
+ } else {
+ this.selectedBigObject = null
+ }
+ },
+ buildSelectedBigObjectInfo() {
+ let obj = this.selectedBigObject
+ return obj.label + ' [' + toSizeString(obj.value) + ', '
+ + ((obj.value) / this.totalSize * 100).toPrecision(3) + '%]'
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ activeNames: ['1', '2'],
+ details: null,
+ totalSize: 0,
+ selectedBigObject: null,
+ cellStyle: {padding: '8px'},
+
+ bigObjects: [],
+ chartData: {},
+ chartOptions: {
+ legend: false,
+ responsive: true,
+ maintainAspectRatio: false,
+ pieceLabel: {
+ mode: 'percentage',
+ precision: 1
+ },
+ animation: {
+ // animateScale: true,
+ // easing: 'linear'
+ },
+ onClick: this.selectBigObject
+ }
+ };
+ },
+ created() {
+ this.loading = true
+
+ axios.get(heapDumpService(this.file, 'details')).then(resp => {
+
+ this.$emit("setGenerationInfoAvailable", resp.data.generationInfoAvailable)
+
+ this.totalSize = resp.data.usedHeapSize
+ this.details = [
+ {
+ key: this.$t("jifa.heap.usedHeapSize"),
+ value: toSizeString(resp.data.usedHeapSize)
+ },
+ {
+ key: this.$t("jifa.heap.numberOfClasses"),
+ value: toCountString(resp.data.numberOfClasses)
+ },
+ {
+ key: this.$t("jifa.heap.numberOfObjects"),
+ value: toCountString(resp.data.numberOfObjects)
+ },
+ {
+ key: this.$t("jifa.heap.numberOfClassLoaders"),
+ value: toCountString(resp.data.numberOfClassLoaders)
+ },
+ {
+ key: this.$t("jifa.heap.numberOfGCRoots"),
+ value: toCountString(resp.data.numberOfGCRoots)
+ },
+ {
+ key: this.$t("jifa.heap.heapCreationDate"),
+ value: formatDate(new Date(resp.data.creationDate), 'yyyy-MM-dd HH:mm:ss')
+ },
+ {
+ key: this.$t("jifa.heap.OSBit"),
+ value: resp.data.identifierSize === 8 ? '64 bit' : '32 bit'
+ },
+ ]
+
+ axios.get(heapDumpService(this.file, 'biggestObjects')).then(resp => {
+ this.bigObjects = resp.data;
+ let labels = []
+ let data = []
+ for (let i = 0; i < resp.data.length; i++) {
+ labels.push(this.bigObjects[i].label)
+ data.push(this.bigObjects[i].value)
+ }
+
+ let color = []
+ for (let i = 0; i < resp.data.length - 1; i++) {
+ color.push(a2rgb(PIE_COLORS[i % PIE_COLORS.length]))
+ }
+
+ if (this.bigObjects[this.bigObjects.length - 1].objectId === -1
+ || this.bigObjects[this.bigObjects.length - 1].label === 'Remainder') {
+ color.push(a2rgb(REMAINDER_COLOR))
+ } else {
+ color.push(a2rgb((this.bigObjects.length - 1) % PIE_COLORS.length))
+ }
+
+ this.chartData = {
+ labels: labels,
+ datasets: [
+ {
+ backgroundColor: color,
+ data: data,
+ }
+ ]
+ }
+ this.loading = false
+ }).catch(() => {
+ this.chartData = {}
+ })
+ })
+ }
+ };
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/SystemProperty.vue b/frontend/src/components/heapdump/SystemProperty.vue
new file mode 100644
index 0000000..4ed3e08
--- /dev/null
+++ b/frontend/src/components/heapdump/SystemProperty.vue
@@ -0,0 +1,83 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <el-table :data="systemProperties.filter(data => !keyword || data.key.toLowerCase().includes(keyword.toLowerCase())
+ || data.value.toLowerCase().includes(keyword.toLowerCase()))"
+ :highlight-current-row="false"
+ height="100%"
+ stripe
+ v-loading="loading"
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ :span-method="tableSpanMethod">
+ <el-table-column label="Key" prop="key" width="400px">
+ </el-table-column>
+ <el-table-column label="Value" prop="value">
+ </el-table-column>
+ <el-table-column align="right">
+ <template slot="header" slot-scope="scope">
+ <el-input size="mini" v-model="keyword" style="width: 50%;"
+ :placeholder="$t('jifa.typeKeyWord')" clearable/>
+ </template>
+ </el-table-column>
+ </el-table>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ export default {
+ props: ['file'],
+ methods: {
+ fetchSystemProperty() {
+ if (this.systemProperties.length > 0) {
+ return
+ }
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'systemProperties')).then(resp => {
+ let sps = []
+ for (let i in resp.data) {
+ sps.push({
+ key: i,
+ value: resp.data[i]
+ })
+ }
+ this.systemProperties = sps
+ this.loading = false
+ })
+ },
+ tableSpanMethod(i) {
+ if (i.columnIndex === 0) {
+ return [1, 1];
+ } else if (i.columnIndex === 1) {
+ return [1, 2];
+ } else {
+ return [0, 0]
+ }
+ },
+ },
+ data() {
+ return {
+ keyword: '',
+ systemProperties: [],
+ cellStyle: {padding: '0'},
+ headerCellStyle: {'font-size': '12px', 'font-weight': 'normal'},
+ loading: false,
+ }
+ },
+ created() {
+ this.fetchSystemProperty()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/Thread.vue b/frontend/src/components/heapdump/Thread.vue
new file mode 100644
index 0000000..42f6c1e
--- /dev/null
+++ b/frontend/src/components/heapdump/Thread.vue
@@ -0,0 +1,310 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <el-table ref="table" :data="threads"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ v-loading="loading"
+ height="100%"
+ :indent=8
+ :load="loadStackInfo"
+ :span-method="tableSpanMethod">
+ <el-table-column label="Thread / Stack" width="450px" show-overflow-tooltip>
+ <template slot-scope="scope">
+ <span v-if="scope.row.isThread" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="threadIcon"/> {{scope.row.object}}
+ </span>
+
+ <span v-if="scope.row.isStack">
+ <img :src="frameIcon"/> {{scope.row.stack}}
+ </span>
+
+ <span v-if="scope.row.isLocal" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon">
+ <strong>{{ " " +scope.row.prefix + " "}}</strong>
+ {{scope.row.label}}
+ <span style="font-weight: bold; color: #909399">{{ " " + scope.row.suffix}}</span>
+ </span>
+
+ <span v-if="scope.row.isOutbound" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="scope.row.icon">
+ <strong>{{ " " +scope.row.prefix + " "}}</strong>
+ {{scope.row.label}}
+ <span style="font-weight: bold; color: #909399">{{ " " + scope.row.suffix}}</span>
+ </span>
+
+ <span v-if="scope.row.isOutboundsSummary">
+ <img :src="ICONS.misc.sumIcon" v-if="scope.row.currentSize >= scope.row.totalSize"/>
+
+ <img :src="ICONS.misc.sumPlusIcon"
+ @dblclick="fetchOutbounds(scope.row.parentRowKey, scope.row.objectId, scope.row.nextPage, scope.row.resolve)"
+ style="cursor: pointer"
+ v-else/>
+ {{ scope.row.currentSize }} <strong> / </strong> {{ scope.row.totalSize }}
+ </span>
+
+ <span v-if="scope.row.isThreadSummaryItem">
+ <img :src="sumIcon" v-if="currentSize >= totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchThreadDetails" style="cursor: pointer" v-else/>
+ {{ currentSize }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="Name" prop="name" width="300px" show-overflow-tooltip>
+ </el-table-column>
+ <el-table-column label="Shallow Heap" prop="shallowHeap">
+ </el-table-column>
+ <el-table-column label="Retained Heap" prop="retainedHeap">
+ </el-table-column>
+ <el-table-column label="Context Class Loader" prop="contextClassLoader" width="420px" show-overflow-tooltip>
+ </el-table-column>
+ <el-table-column label="Is Daemon" prop="daemon">
+ </el-table-column>
+ </el-table>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+ import {getOutboundIcon, ICONS} from './IconHealper'
+
+ let rowKey = 1
+
+ export default {
+ props: ['file'],
+ methods: {
+ loadStackInfo(tree, treeNode, resolve) {
+ if (tree.isThread) {
+ this.fetchStackTrace(tree.objectId, resolve)
+ } else if (tree.isStack) {
+ this.fetchLocals(tree.threadObjectId, tree.depth, tree.firstNonNativeFrame, resolve)
+ } else if (tree.isLocal || tree.isOutbound) {
+ this.fetchOutbounds(tree.rowKey, tree.objectId, 1, resolve)
+ } else if (tree.isOutboundsSummary) {
+ this.fetchOutbounds(tree.parentRowKey, tree.objectId, tree.nextPage, resolve)
+ }
+ },
+ tableSpanMethod(i) {
+ if (i.row.isStack) {
+ if (i.columnIndex === 0) {
+ return [1, 2];
+ } else if (i.columnIndex === 1) {
+ return [0, 0];
+ } else {
+ return [1, 1]
+ }
+ }
+
+ if (i.row.isLocal || i.row.isOutbound) {
+ if (i.columnIndex === 0) {
+ return [1, 2];
+ } else if (i.columnIndex === 1) {
+ return [0, 0];
+ } else {
+ return [1, 1]
+ }
+ }
+ },
+ fetchOutbounds(parentRowKey, objectId, page, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'outbounds'), {
+ params: {
+ objectId: objectId,
+ page: page,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let loadedLen = 0;
+ let loaded = this.$refs['table'].store.states.lazyTreeNodeMap[parentRowKey]
+ let callResolve = false
+ if (loaded) {
+ loadedLen = loaded.length
+ if (loadedLen > 0) {
+ loaded.splice(--loadedLen, 1)
+ }
+ } else {
+ loaded = []
+ callResolve = true;
+ }
+ let res = resp.data.data
+ for (let i = 0; i < res.length; i++) {
+ loaded.push({
+ rowKey: rowKey++,
+ isOutbound: true,
+ objectId: res[i].objectId,
+ prefix: res[i].prefix,
+ label: res[i].label,
+ suffix: res[i].suffix,
+ shallowHeap: res[i].shallowSize,
+ retainedHeap: res[i].retainedSize,
+ icon: getOutboundIcon(res[i].gCRoot, res[i].objectType),
+ hasChildren: res[i].hasOutbound
+ })
+ }
+
+ loaded.push({
+ rowKey: rowKey++,
+ objectId: objectId,
+ parentRowKey: parentRowKey,
+ isOutboundsSummary: true,
+ nextPage: page + 1,
+ currentSize: loadedLen + res.length,
+ totalSize: resp.data.totalSize,
+ resolve: resolve,
+ })
+
+ if (callResolve) {
+ resolve(loaded)
+ }
+ this.loading = false
+ })
+
+ },
+ fetchLocals(objId, depth, firstNonNativeFrame, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'locals'), {
+ params: {
+ objectId: objId,
+ depth: depth,
+ firstNonNativeFrame: firstNonNativeFrame
+ }
+ }).then(resp => {
+ let res = resp.data
+ let locals = []
+ for (let i = 0; i < res.length; i++) {
+ locals.push({
+ rowKey: rowKey++,
+ isLocal: true,
+ objectId: res[i].objectId,
+ prefix: res[i].prefix,
+ label: res[i].label,
+ suffix: res[i].suffix,
+ shallowHeap: res[i].shallowSize,
+ retainedHeap: res[i].retainedSize,
+ icon: getOutboundIcon(res[i].gCRoot, res[i].objectType),
+ hasChildren: res[i].hasOutbound
+ })
+ }
+ resolve(locals)
+ this.loading = false
+ })
+ },
+ fetchStackTrace(objId, resolve) {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'stackTrace'), {
+ params: {
+ objectId: objId
+ }
+ }).then(resp => {
+ let res = resp.data
+ let stacks = []
+ let depth = 1
+ for (let i = 0; i < res.length; i++) {
+ stacks.push({
+ rowKey: rowKey++,
+ isStack: true,
+ threadObjectId: objId,
+ stack: res[i].stack,
+ depth: depth++,
+ hasChildren: res[i].hasLocal,
+ firstNonNativeFrame: res[i].firstNonNativeFrame
+ })
+ }
+ resolve(stacks)
+ this.loading = false
+ })
+ },
+ fetchThreadsData() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'threadsSummary'), {}).then(resp => {
+ this.shallowHeap = resp.data.shallowHeap
+ this.retainedHeap = resp.data.retainedHeap
+ this.totalSize = resp.data.totalSize
+ this.fetchThreadDetails();
+ })
+ },
+ fetchThreadDetails() {
+ if (this.currentSize >= this.totalSize) {
+ return
+ }
+ this.loading = true
+ if (this.nextPage > 1) {
+ this.threads.splice(this.threads.length - 1, 1)
+ }
+ axios.get(heapDumpService(this.file, 'threads'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize
+ }
+ }).then(resp => {
+ let res = resp.data.data
+ let tmp = []
+ this.currentSize += res.length
+ for (let i = 0; i < res.length; i++) {
+ tmp.push({
+ rowKey: rowKey++,
+ isThread: true,
+ objectId: res[i].objectId,
+ object: res[i].object,
+ name: res[i].name,
+ shallowHeap: res[i].shallowSize,
+ retainedHeap: res[i].retainedSize,
+ contextClassLoader: res[i].contextClassLoader,
+ daemon: res[i].daemon + '',
+ hasChildren: res[i].hasStack
+ })
+ }
+ this.nextPage++
+ tmp.forEach(t => this.threads.push(t))
+ this.threads.push({
+ rowKey: rowKey++,
+ isThreadSummaryItem: true,
+ shallowHeap: this.shallowHeap,
+ retainedHeap: this.retainedHeap
+ })
+ this.loading = false
+ })
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ threads: [],
+ ICONS,
+ threadIcon: require('../../assets/heap/thread.gif'),
+ frameIcon: require('../../assets/heap/stack_frame.gif'),
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ nextPage: 1,
+ pageSize: 25,
+ currentSize: 0,
+ totalSize: 0,
+ shallowHeap: 0,
+ retainedHeap: 0,
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'}
+ }
+ },
+ created() {
+ this.fetchThreadsData()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/heapdump/UnreachableObjects.vue b/frontend/src/components/heapdump/UnreachableObjects.vue
new file mode 100644
index 0000000..258aa3f
--- /dev/null
+++ b/frontend/src/components/heapdump/UnreachableObjects.vue
@@ -0,0 +1,143 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <div style="height: 100%">
+ <el-table :data="tableData"
+ :highlight-current-row="false"
+ stripe
+ :header-cell-style="headerCellStyle"
+ :cell-style='cellStyle'
+ row-key="rowKey"
+ lazy
+ :span-method="spanMethod"
+ height="100%"
+ :indent=8
+ v-loading="loading"
+ >
+ <el-table-column label="Class Name">
+ <template slot-scope="scope">
+ <span v-if="scope.row.isRecord" @click="$emit('setSelectedObjectId', scope.row.objectId)"
+ style="cursor: pointer">
+ <img :src="classIcon"/> {{scope.row.className}}
+ </span>
+
+ <span v-if="scope.row.isSummary">
+ <img :src="sumIcon" v-if="records.length >= totalSize"/>
+ <img :src="sumPlusIcon" @dblclick="fetchRecords" style="cursor: pointer" v-else/>
+ {{ records.length }} <strong> / </strong> {{totalSize}}
+ </span>
+ </template>
+ </el-table-column>
+
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+ <el-table-column/>
+
+ <el-table-column label="Objects" prop="objects">
+ </el-table-column>
+
+ <el-table-column label="Shallow Heap" prop="shallowSize">
+ </el-table-column>
+ </el-table>
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ let rowKey = 1
+ export default {
+ props: ['file'],
+ methods: {
+ spanMethod(row) {
+ let index = row.columnIndex
+ if (index === 0) {
+ return [1, 6]
+ } else if (index >= 1 && index <= 5) {
+ return [0, 0]
+ }
+ return [1, 1]
+ },
+ fetchSummary() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'unreachableObjects/summary')).then(resp => {
+ this.totalSize = resp.data.totalSize
+ this.objects = resp.data.objects
+ this.shallowSize = resp.data.shallowSize
+ if (this.totalSize > 0) {
+ this.fetchRecords()
+ } else {
+ this.loading = false
+ }
+ })
+ },
+ fetchRecords() {
+ this.loading = true
+ axios.get(heapDumpService(this.file, 'unreachableObjects/records'), {
+ params: {
+ page: this.nextPage,
+ pageSize: this.pageSize,
+ }
+ }).then(resp => {
+ let records = resp.data.data
+ records.forEach(record => this.records.push({
+ rowKey: rowKey++,
+
+ objectId: record.objectId,
+ className: record.className,
+ objects: record.objects,
+ shallowSize: record.shallowSize,
+
+ isRecord: true,
+ }))
+
+ this.tableData = this.records.concat({
+ rowKey: rowKey++,
+ objects: this.objects,
+ shallowSize: this.shallowSize,
+ isSummary: true
+ })
+
+ this.nextPage++
+ this.loading = false
+ })
+ },
+ },
+ data() {
+ return {
+ classIcon: require('../../assets/heap/objects/class.gif'),
+ sumIcon: require('../../assets/heap/misc/sum.gif'),
+ sumPlusIcon: require('../../assets/heap/misc/sum_plus.gif'),
+ cellStyle: {padding: '4px', fontSize: '12px'},
+ headerCellStyle: {padding: 0, 'font-size': '12px', 'font-weight': 'normal'},
+
+ loading: false,
+
+ objects: 0,
+ shallowSize: 0,
+
+ totalSize: 0,
+ nextPage: 1,
+ pageSize: 25,
+ records: [],
+ tableData: [],
+ }
+ },
+ created() {
+ this.fetchSummary()
+ }
+ }
+</script>
\ No newline at end of file
diff --git a/frontend/src/components/menu/AnalysisResultMenu.vue b/frontend/src/components/menu/AnalysisResultMenu.vue
new file mode 100644
index 0000000..14fe8c8
--- /dev/null
+++ b/frontend/src/components/menu/AnalysisResultMenu.vue
@@ -0,0 +1,96 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <b-navbar-nav>
+ <b-nav-item href="#" @click="doReanalyze" v-if="analysisState === 'SUCCESS' || analysisState === 'ERROR'">
+ <i class="el-icon-warning-outline" style="margin-right: 3px"/> {{$t("jifa.reanalyze")}}
+ </b-nav-item>
+
+ <b-nav-item href="#" @click="doRelease" v-if="analysisState === 'SUCCESS'">
+ <i class="el-icon-s-release" style="margin-right: 3px"/> {{$t("jifa.release")}}
+ </b-nav-item>
+
+ <b-nav-item-dropdown right v-if="analysisState === 'SUCCESS' && type === 'HEAP_DUMP'">
+ <template v-slot:button-content>
+ <i class="el-icon-setting" style="margin-right: 3px"/> {{$t("jifa.setting")}}
+ </template>
+ <b-dropdown-item @click="triggerInspector" style="font-size: 14px">
+ {{showInspector ? $t("jifa.hide") : $t("jifa.show")}} Inspector
+ </b-dropdown-item>
+ <b-dropdown-item @click="$emit('expandResultDivWidth')" style="font-size: 14px">
+ {{$t("jifa.expandResultDivWidth")}}
+ </b-dropdown-item>
+ <b-dropdown-item @click="$emit('shrinkResultDivWidth')" style="font-size: 14px">
+ {{$t("jifa.shrinkResultDivWidth")}}
+ </b-dropdown-item>
+ <b-dropdown-item @click="$emit('resetResultDivWidth')" style="font-size: 14px">
+ {{$t("jifa.resetResultDivWidth")}}
+ </b-dropdown-item>
+ </b-nav-item-dropdown>
+ </b-navbar-nav>
+</template>
+<script>
+ import axios from 'axios'
+ import {heapDumpService} from '../../util'
+
+ export default {
+ props: ['file', 'analysisState', 'type', 'showInspector'],
+
+ methods: {
+
+ doReanalyze() {
+ this.$confirm(this.$t('jifa.heap.reanalyzePrompt'), this.$t('jifa.prompt'), {
+ confirmButtonText: this.$t('jifa.confirm'),
+ cancelButtonText: this.$t('jifa.cancel'),
+ type: 'warning'
+ }).then(() => {
+ axios.post(this.getUrlByType('clean')).then(() => {
+ window.location.reload();
+ })
+ })
+ },
+
+ doRelease() {
+ this.$confirm(this.$t('jifa.heap.releasePrompt'), this.$t('jifa.prompt'), {
+ confirmButtonText: this.$t('jifa.confirm'),
+ cancelButtonText: this.$t('jifa.cancel'),
+ type: 'warning'
+ }).then(() => {
+ axios.post(this.getUrlByType('release')).then(() => {
+ this.$router.push({name: 'finder'})
+ })
+ })
+ },
+
+ triggerInspector() {
+ if (this.type === "HEAP_DUMP") {
+ this.$emit('setShowInspector', !this.showInspector)
+ }
+ },
+
+ getUrlByType(uri) {
+ switch (this.type) {
+ case "HEAP_DUMP":
+ return heapDumpService(this.file, uri);
+ default:
+ return ""
+ }
+ }
+ }
+ }
+</script>
+<style scoped>
+ .navbar-light .navbar-nav .nav-link:focus {
+ color: rgba(0, 0, 0, 0.5);
+ }
+</style>
\ No newline at end of file
diff --git a/frontend/src/components/menu/FinderMenu.vue b/frontend/src/components/menu/FinderMenu.vue
new file mode 100644
index 0000000..ef4c3f2
--- /dev/null
+++ b/frontend/src/components/menu/FinderMenu.vue
@@ -0,0 +1,45 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <b-navbar-nav>
+
+ <b-nav-item @click="$emit('chooseMenu', 'HEAP_DUMP')"
+ :active="fileType==='HEAP_DUMP'">
+ <i class="el-icon-coin" style="margin-right: 3px"/> {{$t("jifa.heapDumpAnalysis")}}
+ </b-nav-item>
+
+ <b-nav-item @click="handleAddFile">
+ <i class="el-icon-plus" style="margin-right: 3px"/> {{this.title}}
+ </b-nav-item>
+ </b-navbar-nav>
+</template>
+
+<script>
+
+ export default {
+ props: ['defaultActive', 'title', 'fileType'],
+ methods: {
+ handleAddFile() {
+ this.$emit('addFile');
+ }
+ },
+ data() {
+ return {}
+ },
+ }
+</script>
+<style scoped>
+ .navbar-light .navbar-nav .nav-link.active {
+ color: #1989FA;
+ }
+</style>
diff --git a/frontend/src/components/menu/ViewMenu.vue b/frontend/src/components/menu/ViewMenu.vue
new file mode 100644
index 0000000..61977e7
--- /dev/null
+++ b/frontend/src/components/menu/ViewMenu.vue
@@ -0,0 +1,76 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template>
+ <b-navbar type="light" variant="faded" style="height: 100%; border-bottom: 1px solid #dcdfe6; font-size: 14px">
+ <b-navbar-nav>
+ <b-navbar-brand href="" to="/">
+ <i class="el-icon-s-platform"/>
+ J I F A
+ </b-navbar-brand>
+ </b-navbar-nav>
+
+ <finder-menu v-if="subject==='finder'" v-bind="$attrs" v-on="$listeners"/>
+ <analysis-result-menu v-else-if="subject==='analysisResult'" v-bind="$attrs" v-on="$listeners"/>
+
+ <b-navbar-nav v-if="subject==='finder'" class="ml-auto">
+ <b-nav-item-dropdown>
+ <template v-slot:button-content>{{currentLanguage}}</template>
+ <b-dropdown-item href="#" v-for="lang in supportLanguages" :key="lang"
+ @click="$i18n.locale=lang.value; currentLanguage=lang.label">
+ {{lang.label}}
+ </b-dropdown-item>
+ </b-nav-item-dropdown>
+ </b-navbar-nav>
+ </b-navbar>
+</template>
+
+<script>
+ import FinderMenu from "./FinderMenu";
+ import AnalysisResultMenu from "./AnalysisResultMenu";
+
+ import {supportLanguages} from '../../i18n/i18n-setup'
+
+
+ export default {
+ props: ['subject'],
+
+ components: {
+ FinderMenu,
+ AnalysisResultMenu,
+ },
+
+ methods: {
+ getCurrentLanguageLabel() {
+ for (let i = 0; i < supportLanguages.length; i++) {
+ let lang = supportLanguages[i]
+ if (lang.value === this.$i18n.locale) {
+ return lang.label
+ }
+ }
+ }
+ },
+
+ data() {
+ return {
+ supportLanguages,
+ currentLanguage: this.getCurrentLanguageLabel(),
+ }
+ },
+ }
+</script>
+
+<style scoped>
+ .navbar-light .navbar-nav .nav-link.active {
+ color: #1989FA;
+ }
+</style>
diff --git a/frontend/src/components/transferFile.vue b/frontend/src/components/transferFile.vue
new file mode 100644
index 0000000..3c2cf33
--- /dev/null
+++ b/frontend/src/components/transferFile.vue
@@ -0,0 +1,447 @@
+<!--
+ Copyright (c) 2020 Contributors to the Eclipse Foundation
+
+ See the NOTICE file(s) distributed with this work for additional
+ information regarding copyright ownership.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License 2.0 which is available at
+ http://www.eclipse.org/legal/epl-2.0
+
+ SPDX-License-Identifier: EPL-2.0
+ -->
+<template xmlns:v-clipboard="http://www.w3.org/1999/xhtml">
+ <div style="margin-top: -20px">
+ <el-dialog
+ width="30%"
+ title="Public Key"
+ :visible.sync="publicKeyViewVisible"
+ append-to-body>
+ <div style="margin-top: -20px">
+ <el-button size="small" round v-clipboard:copy="publicKey" v-clipboard:success="publicKeyCopySuccessfully">
+ {{$t('jifa.copy')}}
+ </el-button>
+ <el-input
+ type="textarea"
+ autosize
+ readonly
+ resize
+ v-model="publicKey" style="margin-top: 20px">
+ </el-input>
+ </div>
+ </el-dialog>
+
+ <el-dialog
+ width="30%"
+ :visible.sync="transferProgressViewVisible"
+ :before-close="closeProgressView"
+ :close-on-press-escape=false :close-on-click-modal=false
+ append-to-body>
+ <el-row>
+ <el-col :span="24" align="center">
+ <el-progress type="circle" :percentage=transferProgress :status="transferState"
+ v-if="totalSize > 0"></el-progress>
+ <b-spinner variant="secondary" type="grow" v-if="totalSize < 0"></b-spinner>
+ </el-col>
+ </el-row>
+ <div style="margin-top: 8px;">
+ <p align="center" style="font-size: 14px"><strong>{{currentProgress}}</strong></p>
+ </div>
+
+ <b-card class="mt-3" bg-variant="dark" text-variant="white" v-if="transferErrorMessage" style="margin-top: 20px">
+ <p style="font-size: 14px; white-space: pre-line;">
+ {{transferErrorMessage}}
+ </p>
+ </b-card>
+ </el-dialog>
+
+ <el-tabs value="upload" style="margin-top: 10px">
+ <el-tab-pane label="Upload" name="upload">
+ <div align="center">
+ <el-upload ref="uploadComp"
+ drag
+ :limit=1
+ :data="{type: fileType}"
+ :action="service('/file/upload')"
+ :multiple=false
+ :on-success="onSuccess">
+ <i class="el-icon-upload"></i>
+ <div class="el-upload__text">{{ $t('jifa.uploadPrompt') }}</div>
+ </el-upload>
+ </div>
+ </el-tab-pane>
+
+ <el-tab-pane label="S C P" name="scp">
+
+ <el-form ref="scpForm" :model="scp" :rules="scpRules" label-width="150px" size="medium" label-position="right"
+ style="margin-top: 10px" :show-message=false status-icon>
+
+ <el-form-item label="">
+ <el-radio-group v-model="scp.authType" @change="changeAuthType">
+ <el-radio label="publicKey">Public Key</el-radio>
+ <el-radio label="password">Password</el-radio>
+ </el-radio-group>
+ </el-form-item>
+
+ <el-form-item label="Hostname" prop="hostname">
+ <el-input v-model="scp.hostname" placeholder="Hostname" style="width: 60%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item label="Path" prop="path">
+ <el-input v-model="scp.path" placeholder="Path" style="width: 60%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item label="User" prop="user">
+ <el-input v-model="scp.user" placeholder="User" style="width: 60%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item label="Password" v-if="scp.authType === 'password'" prop="password">
+ <el-input v-model="scp.password" placeholder="Password" style="width: 60%" clearable
+ show-password></el-input>
+ </el-form-item>
+
+ <el-form-item label="Public Key" v-if="scp.authType === 'publicKey'">
+ <el-button icon="el-icon-view" round @click="loadPublicKey" style="outline:none;"></el-button>
+ </el-form-item>
+
+ <el-form-item>
+ <el-button type="primary" @click="scpConfirm" :disabled="inTransferring">{{$t('jifa.confirm')}}</el-button>
+ </el-form-item>
+
+ </el-form>
+ </el-tab-pane>
+
+ <el-tab-pane label="U R L" name="url">
+ <el-form ref="urlForm" :model="url" :rules="urlRules" label-width="150px" size="medium" label-position="right"
+ style="margin-top: 10px" :show-message=false status-icon>
+ <el-form-item label="U R L" prop="url" :show-message=false>
+ <el-input v-model="url.url" placeholder="U R L" style="width: 80%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item>
+ <el-button type="primary" @click="urlConfirm" :disabled="inTransferring">{{$t('jifa.confirm')}}</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+
+ <el-tab-pane label="File System" name="fileSystem">
+ <el-form ref="fileSystemForm" :model="fileSystem" :rules="fileSystemRules" label-width="150px" size="medium"
+ label-position="right"
+ style="margin-top: 10px" :show-message=false status-icon>
+ <el-form-item label="">
+ <el-radio-group v-model="fileSystem.moveOrCopy">
+ <el-radio label="move">Move</el-radio>
+ <el-radio label="copy">Copy</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="Path" prop="path" :show-message=false>
+ <el-input v-model="fileSystem.path" placeholder="path" style="width: 80%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item>
+ <el-button type="primary" @click="fileSystemConfirm" :disabled="inTransferring">{{$t('jifa.confirm')}}</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+
+ <el-tab-pane label="O S S" name="oss">
+ <el-form ref="ossForm" :model="oss" :rules="ossRules" label-width="150px" size="medium" label-position="right"
+ style="margin-top: 10px" status-icon :show-message=false>
+ <el-form-item label="Endpoint" prop="endpoint">
+ <el-input v-model="oss.endpoint" placeholder="Endpoint" style="width: 80%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item label="Access Key Id" prop="accessKeyId">
+ <el-input v-model="oss.accessKeyId" placeholder="Access Key Id" style="width: 80%" clearable
+ show-password=""></el-input>
+ </el-form-item>
+
+ <el-form-item label="Access Key Secret" prop="accessKeySecret">
+ <el-input v-model="oss.accessKeySecret" placeholder="Access Key Secret" style="width: 80%" clearable
+ show-password=""></el-input>
+ </el-form-item>
+
+ <el-form-item label="Bucket Name" prop="bucketName">
+ <el-input v-model="oss.bucketName" placeholder="Bucket Name" style="width: 80%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item label="Object Name" prop="objectName">
+ <el-input v-model="oss.objectName" placeholder="Object Name" style="width: 80%" clearable></el-input>
+ </el-form-item>
+
+ <el-form-item>
+ <el-button type="primary" @click="ossConfirm" :disabled="inTransferring">{{$t('jifa.confirm')}}</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+
+ </el-tabs>
+
+
+ </div>
+</template>
+
+<script>
+ import axios from 'axios'
+ import {service, toSizeString} from '../util'
+
+ export default {
+ props: ['fileType', 'transferViewVisible'],
+ data() {
+ return {
+ url: {
+ url: '',
+ },
+ urlRules: {
+ url: [
+ {required: true, trigger: 'blur'}
+ ],
+ },
+ fileSystem: {
+ path: '',
+ moveOrCopy: 'move',
+ },
+ fileSystemRules: {
+ path: [
+ {required: true, trigger: 'blur'}
+ ],
+ },
+ scp: {
+ user: '',
+ authType: 'publicKey',
+ password: '',
+ hostname: '',
+ path: '',
+ },
+ scpRules: {
+ user: [
+ {required: true, trigger: 'blur'}
+ ],
+ password: [
+ {required: true, trigger: 'blur'}
+ ],
+ hostname: [
+ {required: true, trigger: 'blur'}
+ ],
+ path: [
+ {required: true, trigger: 'blur'}
+ ],
+ },
+ oss: {
+ endpoint: '',
+ accessKeyId: '',
+ accessKeySecret: '',
+ bucketName: '',
+ objectName: ''
+ },
+ ossRules: {
+ endpoint: [
+ {required: true, trigger: 'blur'}
+ ],
+ accessKeyId: [
+ {required: true, trigger: 'blur'}
+ ],
+ accessKeySecret: [
+ {required: true, trigger: 'blur'}
+ ],
+ bucketName: [
+ {required: true, trigger: 'blur'}
+ ],
+ objectName: [
+ {required: true, trigger: 'blur'}
+ ],
+ },
+
+ publicKeyViewVisible: false,
+ publicKey: '',
+
+ transferProgressViewVisible: false,
+ transferProgress: 0,
+ transferState: null,
+ transferErrorMessage: '',
+ currentProgress: '',
+ lastTransferredSize: 0,
+ transferredSize: 0,
+ totalSize: 0,
+ transferSpeed: 0,
+ fileName: '',
+ pollingInternal: 1000,
+
+ inTransferring: false,
+ }
+ },
+ methods: {
+ service,
+ changeAuthType(authType) {
+ this.$refs['scpForm'].clearValidate()
+ this.scpRules.password[0].required = authType === 'password'
+ },
+ loadPublicKey() {
+ if (!this.publicKey) {
+ axios.get(service('/publicKey')).then(resp => {
+ this.publicKey = resp.data
+ })
+ }
+ this.publicKeyViewVisible = true
+ },
+ publicKeyCopySuccessfully() {
+ this.$message(
+ {
+ duration: 1000,
+ message: this.$t('jifa.copySuccessfully')
+ });
+ },
+ urlConfirm() {
+ this.$refs['urlForm'].validate((valid) => {
+ if (valid) {
+ let formData = new FormData()
+ formData.append('url', this.url.url)
+ this.doTransfer('/file/transferByURL', formData)
+ }
+ })
+ },
+ fileSystemConfirm() {
+ this.$refs['fileSystemForm'].validate((valid) => {
+ if (valid) {
+ let formData = new FormData()
+ formData.append('path', this.fileSystem.path)
+ formData.append('move', this.fileSystem.moveOrCopy === 'move')
+ this.doTransfer('/file/transferByFileSystem', formData)
+ }
+ })
+ },
+ scpConfirm() {
+ this.$refs['scpForm'].validate((valid) => {
+ if (valid) {
+ let usePublicKey = this.scp.authType === 'publicKey'
+ let formData = new FormData()
+ formData.append('hostname', this.scp.hostname)
+ formData.append('path', this.scp.path)
+ formData.append('user', this.scp.user)
+ formData.append('usePublicKey', usePublicKey)
+ if (!usePublicKey) {
+ formData.append('password', this.scp.password)
+ }
+ this.doTransfer('/file/transferBySCP', formData)
+ }
+ })
+ },
+ ossConfirm() {
+ this.$refs['ossForm'].validate((valid) => {
+ if (valid) {
+ let formData = new FormData()
+ formData.append('endpoint', this.oss.endpoint)
+ formData.append('accessKeyId', this.oss.accessKeyId)
+ formData.append('accessKeySecret', this.oss.accessKeySecret)
+ formData.append('bucketName', this.oss.bucketName)
+ formData.append('objectName', this.oss.objectName)
+ this.doTransfer('/file/transferByOSS', formData)
+ }
+ })
+ },
+ jmxConfirm() {
+ this.$refs['jmxForm'].validate((valid) => {
+ if (valid) {
+ let formData = new FormData();
+ formData.append('host', this.jmx.host);
+ formData.append('port', this.jmx.port);
+ this.doTransfer('/file/createJmxConn', formData)
+ }
+ })
+ },
+ onSuccess() {
+ this.transferState = 'success'
+ this.inTransferring = false
+ this.$notify({
+ title: this.$t('jifa.success'),
+ type: 'success',
+ duration: 1500,
+ onClose: () => {
+ // clean
+ if (this.$jifa.dev() && this.$refs['uploadComp']!=null) {
+ this.$refs['uploadComp'].clearFiles()
+ }
+ this.publicKeyViewVisible = false
+ this.transferProgressViewVisible = false
+ this.transferProgress = 0
+ this.transferState = null
+ this.transferErrorMessage = ''
+ this.currentProgress = ''
+ this.lastTransferredSize = 0
+ this.transferredSize = 0
+ this.totalSize = 0
+ this.transferSpeed = 0
+ this.fileName = ''
+ this.$emit('transferFileFinishNotify');
+ }
+ });
+ },
+ transferProgressPoll() {
+ let self = this;
+ if (!self || self._isDestroyed) {
+ return
+ }
+ axios.get(service('/file/transferProgress'), {
+ params: {
+ name: this.fileName,
+ type: this.fileType
+ }
+ }).then(resp => {
+ let progress = resp.data
+ this.totalSize = progress.totalSize
+ this.lastTransferredSize = this.transferredSize
+ this.transferredSize = progress.transferredSize
+ this.currentProgress = toSizeString((this.transferredSize - this.lastTransferredSize) / (this.pollingInternal / 1000))
+ + '/s '
+ + "[" + toSizeString(this.transferredSize)
+ + ", " + (this.totalSize > 0 ? toSizeString(this.totalSize) : " ? ") + "]"
+ if (progress.percent <= 1) {
+ this.transferProgress = parseFloat((progress.percent * 100).toPrecision(3))
+ } else {
+ this.transferProgress = 99.9
+ }
+ if (progress.state === 'SUCCESS') {
+ this.onSuccess()
+ } else if (progress.state === 'ERROR') {
+ this.transferState = 'exception'
+ this.transferErrorMessage = progress.message
+ this.inTransferring = false
+ } else if (progress.state === 'IN_PROGRESS' || progress.state === 'NOT_STARTED') {
+ setTimeout(this.transferProgressPoll, this.pollingInternal)
+ }
+ })
+
+ },
+ doTransfer(api, formData) {
+ this.inTransferring = true
+ this.currentProgress = '0 [0, 0]'
+ this.transferProgress = 0
+ this.transferState = null
+ this.transferErrorMessage = ''
+ this.totalSize = 0
+ this.transferredSize = 0
+ this.lastTransferredSize = 0
+
+ formData.append('type', this.fileType)
+ axios.post(service(api), new URLSearchParams(formData)).then(resp => {
+ this.fileName = resp.data.name
+ this.transferProgressViewVisible = true
+ this.transferProgressPoll()
+ }).catch(e => {
+ this.transferState = 'exception'
+ this.transferErrorMessage = e.response.data.message
+ this.transferProgressViewVisible = true
+ this.inTransferring = false
+ })
+ },
+ closeProgressView(done) {
+ this.$confirm(this.$t('jifa.close') + this.$t('jifa.qm'), '', {
+ confirmButtonText: this.$t('jifa.confirm'),
+ cancelButtonText: this.$t('jifa.cancel'),
+ }).then(() => {
+ done();
+ })
+ },
+ }
+ }
+</script>
diff --git a/frontend/src/i18n/cn.js b/frontend/src/i18n/cn.js
new file mode 100644
index 0000000..439bc3d
--- /dev/null
+++ b/frontend/src/i18n/cn.js
@@ -0,0 +1,116 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+'use strict';
+
+exports.__esModule = true;
+exports.default = {
+ jifa: {
+ heapDumpAnalysis: '堆分析',
+
+ setting: '设置',
+ diskCleanup: '清理磁盘',
+ help: '帮助',
+ consoleMsg: '',
+ getStarted: '开始使用',
+ success: '成功',
+ console: '控制台',
+ setUserWorker: '设置 Worker 地址',
+ qm: '?',
+ feedback: '建议与反馈',
+ options: '选项',
+ optionsWithHelp: '选项',
+ close: '关闭',
+ uploadPrompt: '选择文件(拖拽或点击选择)',
+ enterPrompt: '请输入',
+ inLine: '排队中',
+ addFile: '添加文件',
+ addHeapDumpFile:'添加 Heap Dump',
+ copy: '复制',
+ copySuccessfully: '复制成功',
+ requestFailed: '请求失败',
+ config: '配置',
+ prompt: '提示',
+ confirm: '确定',
+ reset: '重置',
+ cancel: '取消',
+ fileTransfer: '文件传输',
+ progress: '进度',
+ analyze: '分析',
+ reanalyze: '重新分析',
+ release: '释放',
+ edit: '编辑',
+ delete: '删除',
+ loading: '加载中',
+ goToOverViewPrompt: '即将进入概况页面...',
+ deletePrompt: '此操作将永久删除该文件,是否继续?',
+ deleteSuccessPrompt: '删除成功!',
+ deleteFailedPrompt: '删除失败!',
+ deleteCanceled: '已取消删除',
+ returnValue: '确定离开吗?',
+ gotoParseFile: '即将解析文件',
+
+ typeKeyWord: '输入关键字搜索',
+
+ transferring: '传输中',
+ transferError: '传输失败',
+
+ show: '显示',
+ hide: '隐藏',
+
+ expandResultDivWidth: '显示宽度 Expand',
+ shrinkResultDivWidth: '显示宽度 Shrink',
+ resetResultDivWidth: '显示宽度 Reset',
+
+ heap: {
+ basicInformation: '基础信息',
+ reanalyzePrompt: '是否继续?',
+ releasePrompt: '是否继续?',
+ overview: '概况',
+ leakSuspects: '泄露报表',
+ description: '描述',
+ detail: '细节',
+ GCRoots: 'GC 根对象',
+ systemProperty: '系统属性',
+ OSBit: '操作系统位数',
+ jvmInfo: 'JVM',
+ heapCreationDate: '创建时间',
+ usedHeapSize: '堆使用大小',
+ numberOfClasses: '类数量',
+ numberOfObjects: '对象数量',
+ numberOfClassLoaders: '类加载器数量',
+ numberOfGCRoots: '根对象数量',
+ threadInfo: '线程信息',
+ dominatorTree: '支配树',
+ histogram: '类视图',
+ unreachableObjects: '不可达类视图',
+ duplicatedClasses: '重复类视图',
+ classLoaders: '类加载器视图',
+ directByteBuffer: '堆外内存视图',
+ compare: '内存文件对比',
+ ref: {
+ object: {
+ label: '对象引用',
+ outgoing: '引用对象集合',
+ incoming: '被引用对象集合',
+ },
+ type: {
+ label: '类型引用',
+ outgoing: '引用类型集合',
+ incoming: '被引用类型集合',
+ }
+ },
+
+ pathToGCRoots: 'GC 根路径',
+ },
+ }
+};
\ No newline at end of file
diff --git a/frontend/src/i18n/en.js b/frontend/src/i18n/en.js
new file mode 100644
index 0000000..55c03c7
--- /dev/null
+++ b/frontend/src/i18n/en.js
@@ -0,0 +1,118 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+'use strict';
+
+exports.__esModule = true;
+exports.default = {
+ jifa: {
+ heapDumpAnalysis: 'Heap Dump Analysis',
+
+ setting: 'Setting',
+ diskCleanup: 'Disk Cleanup',
+ help: 'Help',
+ consoleMsg: '',
+ getStarted: 'Get Started',
+ success: 'Success',
+ console: 'Console',
+ setUserWorker: 'Set Worker',
+ qm: '?',
+ feedback: 'Feedback',
+ options: 'Options',
+ optionsWithHelp: 'Options',
+ close: 'Close',
+ uploadPrompt: 'Choose your file (drag or click)',
+ enterPrompt: 'Please enter ',
+ inLine: 'In Line',
+ addFile: 'Add File',
+ addHeapDumpFile:'Add Heap Dump File',
+ copy: 'Copy',
+ copySuccessfully: 'Copy Successfully',
+ requestFailed: 'Request failed',
+ config: 'Config',
+ prompt: 'Prompt',
+ confirm: 'Confirm',
+ reset: 'Reset',
+ cancel: 'Cancel',
+ fileTransfer: 'File Transfer',
+ progress: 'Progress',
+ analyze: 'analyze',
+ reanalyze: 'Reanalyze',
+ release: 'Release',
+ edit: 'edit',
+ delete: 'Delete',
+ loading: 'Loading',
+ goToOverViewPrompt: 'Go to the overview page',
+ deletePrompt: 'This will permanently delete the file. Do you want to continue?',
+ deleteSuccessPrompt: 'Delete success!',
+ deleteFailedPrompt: 'Delete failed!',
+ deleteCanceled: 'Delete operation is canceled',
+ returnValue: 'Are you sure to leave?',
+ gotoParseFile: 'Will go to parse file',
+
+ typeKeyWord: 'type key word to search',
+
+ transferring: 'transferring',
+ transferError: 'transfer error',
+
+ show: 'Show',
+ hide: 'Hide',
+
+ expandResultDivWidth: 'Expand Width',
+ shrinkResultDivWidth: 'Shrink Width',
+ resetResultDivWidth: 'Reset Width',
+
+ addResultDivWidth: 'Add width',
+
+ heap: {
+ basicInformation: 'Basic Information',
+ reanalyzePrompt: 'Do you want to continue?',
+ releasePrompt: 'Do you want to continue?',
+ overview: 'Overview',
+ leakSuspects: 'Leak Suspects',
+ description: 'Description',
+ detail: 'Detail',
+ GCRoots: 'GC Roots',
+ systemProperty: 'System Property',
+ OSBit: 'OS Bit',
+ jvmInfo: 'JVM',
+ heapCreationDate: 'Creation Date',
+ usedHeapSize: 'Used Heap Size',
+ numberOfClasses: 'Class Count',
+ numberOfObjects: 'Object Count',
+ numberOfClassLoaders: 'Class Loaders Count',
+ numberOfGCRoots: 'GC Root Count',
+ threadInfo: 'Thread Info',
+ dominatorTree: 'Dominator Tree',
+ histogram: 'Histogram',
+ unreachableObjects: 'Unreachable Objects',
+ duplicatedClasses: 'Duplicated Classes',
+ classLoaders: 'Class Loaders',
+ directByteBuffer: 'Direct Byte Buffer',
+ compare: 'Heap File Compare',
+ ref: {
+ object: {
+ label: 'References by Object',
+ outgoing: 'outgoing references',
+ incoming: 'incoming references',
+ },
+ type: {
+ label: 'Reference by Class',
+ outgoing: 'outgoing references',
+ incoming: 'incoming references',
+ }
+ },
+
+ pathToGCRoots: 'Path to GC Roots',
+ },
+ }
+};
\ No newline at end of file
diff --git a/frontend/src/i18n/i18n-setup.js b/frontend/src/i18n/i18n-setup.js
new file mode 100644
index 0000000..792ba30
--- /dev/null
+++ b/frontend/src/i18n/i18n-setup.js
@@ -0,0 +1,38 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import Vue from 'vue'
+import VueI18n from 'vue-i18n'
+import messages from './messages'
+
+import ElementLocale from 'element-ui/lib/locale'
+
+Vue.use(VueI18n)
+
+const i18n = new VueI18n({
+ fallbackLocale: 'en',
+ messages
+})
+
+i18n.locale = 'en'
+
+ElementLocale.i18n((key, value) => i18n.t(key, value))
+
+export default i18n
+
+export const supportLanguages = [{
+ label: 'English',
+ value: 'en'
+}, {
+ label: '中文',
+ value: 'cn'
+},]
diff --git a/frontend/src/i18n/messages.js b/frontend/src/i18n/messages.js
new file mode 100644
index 0000000..d014cde
--- /dev/null
+++ b/frontend/src/i18n/messages.js
@@ -0,0 +1,29 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import element_ui_enLocale from 'element-ui/lib/locale/lang/en'
+import element_ui_zhLocale from 'element-ui/lib/locale/lang/zh-CN'
+
+import en from './en'
+import cn from './cn'
+
+export default {
+ en: {
+ ...en,
+ ...element_ui_enLocale,
+ },
+
+ cn: {
+ ...cn,
+ ...element_ui_zhLocale
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/main.js b/frontend/src/main.js
new file mode 100644
index 0000000..5cf20bf
--- /dev/null
+++ b/frontend/src/main.js
@@ -0,0 +1,51 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import Vue from 'vue'
+
+import Jifa from './Jifa.vue'
+import JifaGlobal from './Jifa'
+
+import i18n from './i18n/i18n-setup'
+import router from './router'
+
+import ElementUI from 'element-ui'
+import BootstrapVue from 'bootstrap-vue'
+import VueCharts from 'vue-chartjs'
+import VueClipboard from 'vue-clipboard2'
+import contentmenu from 'v-contextmenu'
+
+import VueCookies from 'vue-cookies'
+
+import 'v-contextmenu/dist/index.css'
+import 'bootstrap/dist/css/bootstrap.css'
+import 'bootstrap-vue/dist/bootstrap-vue.css'
+import 'element-ui/lib/theme-chalk/index.css'
+// put our css file in the end
+import './Jifa.css'
+
+Vue.use(ElementUI)
+Vue.use(BootstrapVue)
+Vue.use(VueCharts)
+Vue.use(VueClipboard)
+Vue.use(contentmenu)
+Vue.use(VueCookies)
+Vue.prototype.$jifa = JifaGlobal
+
+export default new Vue({
+ router,
+ i18n,
+ render: h => h(Jifa),
+ created() {
+ console.log(this.$t("jifa.consoleMsg"))
+ }
+}).$mount('#app')
\ No newline at end of file
diff --git a/frontend/src/router.js b/frontend/src/router.js
new file mode 100644
index 0000000..b8790d6
--- /dev/null
+++ b/frontend/src/router.js
@@ -0,0 +1,75 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+import Vue from "vue"
+
+import VueRouter from "vue-router"
+
+import finder from "./components/finder"
+
+import heapDump from "./components/heapdump/HeapDump"
+
+import axios from "axios";
+
+import notFound from "./components/404"
+
+import VueInsatence from "./main"
+
+Vue.use(VueRouter)
+
+const routes = [
+ {
+ name: 'finder',
+ path: '/',
+ component: finder
+ },
+ {
+ name: 'heapDump',
+ path: "/heapDump",
+ component: heapDump,
+ props: (route) => ({file: route.query.file})
+ },
+ {path: '*', component: notFound}
+];
+
+const router = new VueRouter({
+ mode: 'history',
+ routes
+});
+
+axios.interceptors.response.use(function (response) {
+ return response;
+}, function (error) {
+ let resp = error.response
+ if (resp) {
+ let status = resp.status
+ let data = resp.data
+ if (status === 500 || status === 400 || status === 401 || status === 403) {
+ if (data && data.hasOwnProperty('errorCode')) {
+ if (data.errorCode === 'TRANSFER_ERROR') {
+ // do nothing
+ } else {
+ VueInsatence.$notify.error({
+ title: data.errorCode,
+ message: data.message,
+ offset: 100,
+ duration: 0,
+ showClose: true
+ });
+ }
+ }
+ }
+ }
+ return Promise.reject(error);
+});
+
+export default router
\ No newline at end of file
diff --git a/frontend/src/util.js b/frontend/src/util.js
new file mode 100644
index 0000000..6df9691
--- /dev/null
+++ b/frontend/src/util.js
@@ -0,0 +1,76 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+export function toSizeString(bytes) {
+ if (bytes <= 1024) return bytes + " B"
+ let k = 1024,
+ suffix = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
+ i = Math.floor(Math.log(bytes) / Math.log(k))
+
+ return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + suffix[i]
+}
+
+export function toCountString(counts) {
+ if (counts <= 1000) return counts + " "
+ let k = 1000,
+ suffix = [' ', 'k', 'm', 'g', 't', 'p', 'e', 'z', 'y'],
+ i = Math.floor(Math.log(counts) / Math.log(k))
+
+ return (counts / Math.pow(k, i)).toPrecision(4) + ' ' + suffix[i]
+}
+
+const SERVICE_PREFIX = '/jifa-api'
+
+export function service(suffix) {
+ return SERVICE_PREFIX + suffix
+}
+
+export function heapDumpService(file, api) {
+ return SERVICE_PREFIX + '/heap-dump/' + file + '/' + api;
+}
+
+export function matchSearch(data,val){
+ let temp = [];
+ for(let index in data){
+ for(let prop in data[index]){
+ // Do not use strict equal operator
+ if(data[index][prop]==val){
+ temp.push(data[index]);
+ }
+ }
+ }
+ return temp;
+}
+
+// e.g. formatTime(1545903266795, 'Y-M-D h:m:s')
+export function formatTime (number, format) {
+ let time = new Date(number)
+ let newArr = []
+ let formatArr = ['Y', 'M', 'D', 'h', 'm', 's']
+ newArr.push(time.getFullYear())
+ newArr.push(formatNumber(time.getMonth() + 1))
+ newArr.push(formatNumber(time.getDate()))
+
+ newArr.push(formatNumber(time.getHours()))
+ newArr.push(formatNumber(time.getMinutes()))
+ newArr.push(formatNumber(time.getSeconds()))
+
+ for (let i in newArr) {
+ format = format.replace(formatArr[i], newArr[i])
+ }
+ return format;
+}
+
+function formatNumber (n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n;
+}
\ No newline at end of file
diff --git a/frontend/vue.config.js b/frontend/vue.config.js
new file mode 100644
index 0000000..e9aa8bf
--- /dev/null
+++ b/frontend/vue.config.js
@@ -0,0 +1,27 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+module.exports = {
+ devServer: {
+ historyApiFallback: {
+ disableDotRule: true
+ },
+ noInfo: true,
+ port: 8089,
+ proxy: {
+ '/jifa-api': {
+ target: 'http://127.0.0.1:8102'
+ },
+ }
+ },
+ publicPath: './'
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..87b738c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9b86d1c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Mar 22 09:38:02 CST 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..af6708f
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..6d57edc
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..512de6d
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/********************************************************************************
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ********************************************************************************/
+rootProject.name = 'Jifa'
+
+include ':frontend'
+include ':backend'
+include ':backend:common'
+include ':backend:worker'