Merge "Cosmetics: Rename local variable in lambda."
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index b764439..a9d922d 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -2766,6 +2766,22 @@
 If not set or set to a zero, defaults to the number of logical CPUs as returned
 by the JVM. If set to a negative value, defaults to a direct executor.
 
+[[index.change.indexMergeable]]index.change.indexMergeable::
++
+Specifies if `mergeable` should be index or not. Indexing this field enables
+queries that contain the mergeability operator (`is:mergeable`). If enabled,
+Gerrit will check if the change is mergeable into the target branch when
+reindexing a change. This is an expensive operation.
++
+If true, Gerrit will reindex all open changes when the target ref advances.
+Depending on the frequency of updates to the ref and the number of open changes,
+this can be very expensive.
++
+When this setting is changed from `false` to `true`, all changes need to be
+reindexed.
++
+Defaults to true.
+
 [[index.onlineUpgrade]]index.onlineUpgrade::
 +
 Whether to upgrade to new index schema versions while the server is
@@ -2813,19 +2829,6 @@
 +
 Defaults to 1024.
 
-[[index.reindexAfterRefUpdate]]index.reindexAfterRefUpdate::
-+
-Whether to reindex all affected open changes after a ref is updated. This
-includes reindexing all open changes to recompute the "mergeable" bit every time
-the destination branch moves, as well as reindexing changes to take into account
-new project configuration (e.g. label definitions).
-+
-Leaving this enabled may result in fresher results, but may cause performance
-problems if there are lots of open changes on a project whose branches advance
-frequently.
-+
-Defaults to true.
-
 [[index.autoReindexIfStale]]index.autoReindexIfStale::
 +
 Whether to automatically check if a document became stale in the index
@@ -4095,7 +4098,8 @@
 The default size of the background execution thread pool in
 which miscellaneous tasks are handled.
 +
-Default is 1.
+Default and minimum is 2 so that a single, potentially longer executing
+task (e.g. GC), is not blocking the entire execution.
 
 [[execution.fanOutThreadPoolSize]]execution.fanOutThreadPoolSize::
 +
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index e9e4ae6..63dabc4 100644
--- a/Documentation/dev-bazel.txt
+++ b/Documentation/dev-bazel.txt
@@ -31,17 +31,17 @@
 
 `java -version`
 
-[[java-12]]
-==== Java 12 support
+[[java-13]]
+==== Java 13 support
 
-Java 12 (and newer) is supported through vanilla java toolchain
+Java 13 (and newer) is supported through vanilla java toolchain
 link:https://docs.bazel.build/versions/master/toolchains.html[Bazel option].
-To build Gerrit with Java 12 and newer, specify vanilla java toolchain and
+To build Gerrit with Java 13 and newer, specify vanilla java toolchain and
 provide the path to JDK home:
 
 ```
   $ bazel build \
-    --define=ABSOLUTE_JAVABASE=<path-to-java-12> \
+    --define=ABSOLUTE_JAVABASE=<path-to-java-13> \
     --javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
@@ -54,7 +54,7 @@
 
 ```
   $ bazel test \
-    --define=ABSOLUTE_JAVABASE=<path-to-java-12> \
+    --define=ABSOLUTE_JAVABASE=<path-to-java-13> \
     --javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
@@ -67,7 +67,7 @@
 
 ```
 $ cat << EOF > ~/.bazelrc
-> build --define=ABSOLUTE_JAVABASE=<path-to-java-12>
+> build --define=ABSOLUTE_JAVABASE=<path-to-java-13>
 > build --javabase=@bazel_tools//tools/jdk:absolute_javabase
 > build --host_javabase=@bazel_tools//tools/jdk:absolute_javabase
 > build --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 223ec71..b7b807f 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -452,8 +452,8 @@
 [source,java]
 ----
 import com.google.gerrit.common.EventDispatcher;
+import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.exceptions.StorageException;
 import com.google.inject.Inject;
 
 class MyPlugin {
diff --git a/Documentation/intro-gerrit-walkthrough.txt b/Documentation/intro-gerrit-walkthrough.txt
index b4f799c2..a631b47 100644
--- a/Documentation/intro-gerrit-walkthrough.txt
+++ b/Documentation/intro-gerrit-walkthrough.txt
@@ -186,6 +186,7 @@
 
 * Check out the commit
 * Amend the commit
+* Rebase the commit if needed
 * Push the commit to Gerrit
 
 ----
@@ -195,6 +196,20 @@
 [master 30a6f44] Change to a proper, yeast based pizza dough.
  Date: Fri Jun 8 16:28:23 2018 +0200
  1 file changed, 10 insertions(+), 5 deletions(-)
+----
+
+At this point Max wants to make sure that his change is on top of the branch.
+
+----
+$ git fetch
+$
+----
+
+Max got no output from the fetch command, which is good news.
+This means that the master branch has not progressed and there is no need for link:intro-user.html#rebase[*rebase*].
+Max is now ready to push his change:
+
+----
 $ git push origin HEAD:refs/for/master
 Counting objects: 3, done.
 Delta compression using up to 8 threads.
diff --git a/Documentation/licenses.txt b/Documentation/licenses.txt
index ac25816..394886d 100644
--- a/Documentation/licenses.txt
+++ b/Documentation/licenses.txt
@@ -65,7 +65,6 @@
 * httpcomponents:httpcore
 * httpcomponents:httpcore-nio
 * jackson:jackson-core
-* jetty:continuation
 * jetty:http
 * jetty:io
 * jetty:jmx
@@ -89,6 +88,8 @@
 * openid:xerces
 * polymer_externs:polymer_closure
 * blame-cache
+* caffeine
+* caffeine-guava
 * gson
 * guava
 * guava-failureaccess
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 7097a16..6ef4e20 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -2143,7 +2143,7 @@
 * a user name ("username")
 
 In all cases, accounts that are not
-link:config-gerrit.txt#accounts.visibility[visible] to the calling user are not
+link:config-gerrit.html#accounts.visibility[visible] to the calling user are not
 considered.
 
 In all cases _except_ a bare account ID and `self`/`me`, inactive accounts are
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 4165f93..0fc733a 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -315,6 +315,11 @@
 the `mergeable` field will always be omitted and `SKIP_MERGEABLE` has no
 effect.
 +
+When link:config-gerrit.html#index.change.indexMergeable[
+`index.change.indexMergeable`] is set to `false` in the `gerrit.config`,
+the `mergeable` field will always be omitted when querying changes and
+`SKIP_MERGEABLE` has no effect.
++
 A change's mergeability can be requested separately by calling the
 link:#get-mergeable[get-mergeable] endpoint.
 --
@@ -6010,6 +6015,8 @@
 When present, change has been marked Ready at some point in time.
 |`revert_of`          |optional|
 The numeric Change-Id of the change that this change reverts.
+|`submission_id`      |optional|
+ID of the submission of this change. Only set if the status is `MERGED`.
 |==================================
 
 [[change-input]]
diff --git a/Documentation/rest-api-groups.txt b/Documentation/rest-api-groups.txt
index 00fd81f..a99c3bb 100644
--- a/Documentation/rest-api-groups.txt
+++ b/Documentation/rest-api-groups.txt
@@ -341,24 +341,19 @@
 [[query-groups]]
 === Query Groups
 --
-'GET /groups/?query2=<query>'
+'GET /groups/?query=<query>'
 --
 
 Queries internal groups visible to the caller. The
 link:user-search-groups.html#_search_operators[query string] must be
-provided by the `query2` parameter. The `start` and `limit` parameters
+provided by the `query` parameter. The `start` and `limit` parameters
 can be used to skip/limit results.
 
 As result a list of link:#group-info[GroupInfo] entities is returned.
 
-[NOTE] `query2` is a temporary name and in future this option may be
-renamed to `query`. `query2` was chosen to maintain backwards
-compatibility with the deprecated `query` parameter on the
-link:#list-groups[List Groups] endpoint.
-
 .Request
 ----
-  GET /groups/?query2=inname:test HTTP/1.0
+  GET /groups/?query=inname:test HTTP/1.0
 ----
 
 .Response
@@ -398,12 +393,12 @@
 
 [[group-query-limit]]
 ==== Group Limit
-The `/groups/?query2=<query>` URL also accepts a limit integer in the
+The `/groups/?query=<query>` URL also accepts a limit integer in the
 `limit` parameter. This limits the results to `limit` groups.
 
 Query the first 25 groups in group list.
 ----
-  GET /groups/?query2=<query>&limit=25 HTTP/1.0
+  GET /groups/?query=<query>&limit=25 HTTP/1.0
 ----
 
 The `/groups/` URL also accepts a start integer in the `start`
@@ -411,7 +406,7 @@
 
 Query 25 groups starting from index 50.
 ----
-  GET /groups/?query2=<query>&limit=25&start=50 HTTP/1.0
+  GET /groups/?query=<query>&limit=25&start=50 HTTP/1.0
 ----
 
 [[group-query-options]]
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 74ec8d3..c373b96 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -3233,6 +3233,66 @@
   HTTP/1.1 204 No Content
 ----
 
+[[batch-update-labels]]
+=== Batch Update Labels
+--
+'POST /projects/link:#project-name[\{project-name\}]/labels/'
+--
+
+Creates/updates/deletes multiple label definitions in this project at once.
+
+The calling user must have write access to the `refs/meta/config` branch of the
+project.
+
+The updates must be specified in the request body as
+link:#batch-label-input[BatchLabelInput] entity.
+
+The updates are processed in the following order:
+
+1. label deletions
+2. label creations
+3. label updates
+
+.Request
+----
+  POST /projects/My-Project/labels/ HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "commit_message": "Update Labels",
+    "delete": [
+      "Old-Review",
+      "Unused-Review"
+    ],
+    "create": [
+      {
+        "name": "Foo-Review",
+        "values": {
+          " 0": "No score",
+          "-1": "I would prefer this is not merged as is",
+          "-2": "This shall not be merged",
+          "+1": "Looks good to me, but someone else must approve",
+          "+2": "Looks good to me, approved"
+      }
+    ],
+    "update:" {
+      "Bar-Review": {
+        "function": "MaxWithBlock"
+      },
+      "Baz-Review": {
+        "copy_min_score": true
+      }
+    }
+  }
+----
+
+If the label updates were done successfully the response is "`200 OK`".
+
+.Response
+----
+  HTTP/1.1 200 OK
+----
+
 
 [[ids]]
 == IDs
@@ -3645,8 +3705,6 @@
 |`inherited_value` |optional|
 The inherited value of the configuration parameter, only set if
 `inheritable` is true.
-|`permitted_values` |optional|
-The list of permitted values, only set if the `type` is `LIST`.
 |===============================
 
 [[dashboard-info]]
@@ -3876,9 +3934,14 @@
 |Field Name      ||Description
 |`commit_message`|optional|
 Message that should be used to commit the change of the label in the
-`project.config` file to the `refs/meta/config` branch.
+`project.config` file to the `refs/meta/config` branch.+
+Must not be set if this `LabelDefinitionInput` entity is contained in a
+link:#batch-label-input[BatchLabelInput] entity.
 |`name`          |optional|
-The new link:config-labels.html#label_name[name] of the label.
+The new link:config-labels.html#label_name[name] of the label.+
+For label creation the name is required if this `LabelDefinitionInput` entity
+is contained in a link:#batch-label-input[BatchLabelInput]
+entity.
 |`function`      |optional|
 The new link:config-labels.html#label_function[function] of the label (can be
 `MaxWithBlock`, `AnyWithBlock`, `MaxNoBlock`, `NoBlock`, `NoOp` and `PatchSetLock`.
@@ -3961,6 +4024,27 @@
 Not set if not inherited or overridden.
 |===============================
 
+[[batch-label-input]]
+=== BatchLabelInput
+The `BatchLabelInput` entity contains information for batch updating label
+definitions in a project.
+
+[options="header",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`commit_message`|optional|
+Message that should be used to commit the label updates in the
+`project.config` file to the `refs/meta/config` branch.
+|`delete`        |optional|
+List of labels that should be deleted.
+|`create`        |optional|
+List of link:#label-definition-input[LabelDefinitionInput] entities that
+describe labels that should be created.
+|`update`        |optional|
+Map of label names to link:#label-definition-input[LabelDefinitionInput]
+entities that describe the updates that should be done for the labels.
+|=============================
+
 [[project-access-input]]
 === ProjectAccessInput
 The `ProjectAccessInput` describes changes that should be applied to a project
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 55a9ab7..bde9508 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -140,6 +140,11 @@
 +
 Changes that revert the change specified by the numeric 'ID'.
 
+[[submissionid]]
+submissionid:'ID'::
++
+Changes that have the specified submission 'ID'.
+
 [[reviewerin]]
 reviewerin:'GROUP'::
 +
diff --git a/Jenkinsfile b/Jenkinsfile
index cd0a7e7..257b53c 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -139,7 +139,7 @@
     def polygerritFiles = changedFiles.findAll { it.startsWith("polygerrit-ui") ||
         it.startsWith("lib/js") }
 
-    if(polygerritFiles.size() > 0 || changedFiles.contains("WORKSPACE")) {
+    if(polygerritFiles.size() > 0) {
         if(changedFiles.size() == polygerritFiles.size()) {
             println "Only PolyGerrit UI changes detected, skipping other test modes..."
             Builds.modes = ["polygerrit"]
@@ -147,6 +147,9 @@
             println "PolyGerrit UI changes detected, adding 'polygerrit' validation..."
             Builds.modes += "polygerrit"
         }
+    } else if(changedFiles.contains("WORKSPACE")) {
+        println "WORKSPACE file changes detected, adding 'polygerrit' validation..."
+        Builds.modes += "polygerrit"
     }
 }
 
diff --git a/WORKSPACE b/WORKSPACE
index ac3d5e0..7529d8a 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -241,10 +241,29 @@
     sha1 = "1dcf1de382a0bf95a3d8b0849546c88bac1292c9",
 )
 
+CAFFEINE_VERS = "2.8.0"
+
 maven_jar(
-    name = "j2objc",
-    artifact = "com.google.j2objc:j2objc-annotations:1.1",
-    sha1 = "ed28ded51a8b1c6b112568def5f4b455e6809019",
+    name = "caffeine",
+    artifact = "com.github.ben-manes.caffeine:caffeine:" + CAFFEINE_VERS,
+    sha1 = "6000774d7f8412ced005a704188ced78beeed2bb",
+)
+
+# TODO(davido): Rename guava.jar to caffeine-guava.jar on fetch to prevent potential
+# naming collision between caffeine guava adapater and guava library itself.
+# Remove this renaming procedure, once this upstream issue is fixed:
+# https://github.com/ben-manes/caffeine/issues/364.
+http_file(
+    name = "caffeine-guava-renamed",
+    downloaded_file_path = "caffeine-guava-" + CAFFEINE_VERS + ".jar",
+    sha256 = "3a66ee3ec70971dee0bae6e56bda7b8742bc4bedd7489161bfbbaaf7137d89e1",
+    urls = [
+        "https://repo1.maven.org/maven2/com/github/ben-manes/caffeine/guava/" +
+        CAFFEINE_VERS +
+        "/guava-" +
+        CAFFEINE_VERS +
+        ".jar",
+    ],
 )
 
 maven_jar(
@@ -729,7 +748,7 @@
     sha1 = "f7be08ec23c21485b9b5a1cf1654c2ec8c58168d",
 )
 
-GITILES_VERS = "0.3-5"
+GITILES_VERS = "0.3-6"
 
 GITILES_REPO = GERRIT
 
@@ -738,14 +757,14 @@
     artifact = "com.google.gitiles:blame-cache:" + GITILES_VERS,
     attach_source = False,
     repository = GITILES_REPO,
-    sha1 = "22d5e48827bd48b9e7b049bb9726ef017fda9eca",
+    sha1 = "bd1ec86570b8a6e4b68c5af6311c8cd10aa3f295",
 )
 
 maven_jar(
     name = "gitiles-servlet",
     artifact = "com.google.gitiles:gitiles-servlet:" + GITILES_VERS,
     repository = GITILES_REPO,
-    sha1 = "061de6d5ef22be870300cc01a6fb205bb7782eae",
+    sha1 = "98bf06ca9abc871beb3d6c01e6f053243d4e911a",
 )
 
 # prettify must match the version used in Gitiles
@@ -774,12 +793,6 @@
     sha1 = "198ea005f41219f038f4291f0b0e9f3259730e92",
 )
 
-maven_jar(
-    name = "dropwizard-core",
-    artifact = "io.dropwizard.metrics:metrics-core:4.1.1",
-    sha1 = "ebfafc716d9c3b6151dc7c2c09ce925a163a4f21",
-)
-
 # When updating Bouncy Castle, also update it in bazlets.
 BC_VERS = "1.61"
 
@@ -801,38 +814,6 @@
     sha1 = "89bb3aa5b98b48e584eee2a7401b7682a46779b4",
 )
 
-SSHD_VERS = "2.3.0"
-
-maven_jar(
-    name = "sshd",
-    artifact = "org.apache.sshd:sshd-core:" + SSHD_VERS,
-    sha1 = "21aeea9deba96c9b81ea0935fa4fac61aa3cf646",
-)
-
-maven_jar(
-    name = "sshd-common",
-    artifact = "org.apache.sshd:sshd-common:" + SSHD_VERS,
-    sha1 = "8b6e3baaa0d35b547696965eef3e62477f5e74c9",
-)
-
-maven_jar(
-    name = "sshd-mina",
-    artifact = "org.apache.sshd:sshd-mina:" + SSHD_VERS,
-    sha1 = "55dc0830dfcbceba01f9460812ee454978a15fe8",
-)
-
-maven_jar(
-    name = "eddsa",
-    artifact = "net.i2p.crypto:eddsa:0.3.0",
-    sha1 = "1901c8d4d8bffb7d79027686cfb91e704217c3e1",
-)
-
-maven_jar(
-    name = "mina-core",
-    artifact = "org.apache.mina:mina-core:2.0.21",
-    sha1 = "e1a317689ecd438f54e863747e832f741ef8e092",
-)
-
 maven_jar(
     name = "h2",
     artifact = "com.h2database:h2:1.3.176",
@@ -861,20 +842,6 @@
     sha1 = "f5aa318bda4c6c8d688c9d00b90681dcd82ce636",
 )
 
-# elasticsearch-rest-client explicitly depends on this version
-maven_jar(
-    name = "httpasyncclient",
-    artifact = "org.apache.httpcomponents:httpasyncclient:4.1.4",
-    sha1 = "f3a3240681faae3fa46b573a4c7e50cec9db0d86",
-)
-
-# elasticsearch-rest-client explicitly depends on this version
-maven_jar(
-    name = "httpcore-nio",
-    artifact = "org.apache.httpcomponents:httpcore-nio:4.4.11",
-    sha1 = "7d0a97d01d39cff9aa3e6db81f21fddb2435f4e6",
-)
-
 # Test-only dependencies below.
 
 maven_jar(
@@ -954,12 +921,6 @@
 )
 
 maven_jar(
-    name = "jetty-continuation",
-    artifact = "org.eclipse.jetty:jetty-continuation:" + JETTY_VERS,
-    sha1 = "3c421a3be5be5805e32b1a7f9c6046526524181d",
-)
-
-maven_jar(
     name = "jetty-http",
     artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VERS,
     sha1 = "c2e73db2db5c369326b717da71b6587b3da11e0e",
@@ -978,25 +939,6 @@
 )
 
 maven_jar(
-    name = "openid-consumer",
-    artifact = "org.openid4java:openid4java:1.0.0",
-    sha1 = "541091bb49f2c0d583544c5bb1e6df7612d31e3e",
-)
-
-maven_jar(
-    name = "nekohtml",
-    artifact = "net.sourceforge.nekohtml:nekohtml:1.9.10",
-    sha1 = "14052461031a7054aa094f5573792feb6686d3de",
-)
-
-maven_jar(
-    name = "xerces",
-    artifact = "xerces:xercesImpl:2.8.1",
-    attach_source = False,
-    sha1 = "25101e37ec0c907db6f0612cbf106ee519c1aef1",
-)
-
-maven_jar(
     name = "commons-io",
     artifact = "commons-io:commons-io:2.2",
     sha1 = "83b5b8a7ba1c08f9e8c8ff2373724e33d3c1e22a",
@@ -1009,58 +951,6 @@
 )
 
 maven_jar(
-    name = "jruby",
-    artifact = "org.jruby:jruby-complete:9.1.17.0",
-    sha1 = "76716d529710fc03d1d429b43e3cedd4419f78d4",
-)
-
-# When upgrading elasticsearch-rest-client, also upgrade httpcore-nio
-# and httpasyncclient as necessary.
-maven_jar(
-    name = "elasticsearch-rest-client",
-    artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.4.2",
-    sha1 = "f48725523c0b3402f869214433602f8d3f4c737c",
-)
-
-maven_jar(
-    name = "jackson-core",
-    artifact = "com.fasterxml.jackson.core:jackson-core:2.10.0",
-    sha1 = "4e2c5fa04648ec9772c63e2101c53af6504e624e",
-)
-
-TESTCONTAINERS_VERSION = "1.12.3"
-
-maven_jar(
-    name = "testcontainers",
-    artifact = "org.testcontainers:testcontainers:" + TESTCONTAINERS_VERSION,
-    sha1 = "e424a4549640e120acceac641ac909fcda58bf62",
-)
-
-maven_jar(
-    name = "testcontainers-elasticsearch",
-    artifact = "org.testcontainers:elasticsearch:" + TESTCONTAINERS_VERSION,
-    sha1 = "c0796de5032070b8768ce78c78949b48f13c30db",
-)
-
-maven_jar(
-    name = "duct-tape",
-    artifact = "org.rnorth.duct-tape:duct-tape:1.0.7",
-    sha1 = "a26b5d90d88c91321dc7a3734ea72d2fc019ebb6",
-)
-
-maven_jar(
-    name = "visible-assertions",
-    artifact = "org.rnorth.visible-assertions:visible-assertions:2.1.2",
-    sha1 = "20d31a578030ec8e941888537267d3123c2ad1c1",
-)
-
-maven_jar(
-    name = "jna",
-    artifact = "net.java.dev.jna:jna:5.2.0",
-    sha1 = "ed8b772eb077a9cb50e44e90899c66a9a6c00e67",
-)
-
-maven_jar(
     name = "javax-activation",
     artifact = "javax.activation:activation:1.1.1",
     sha1 = "485de3a253e23f645037828c07f1d7f1af40763a",
diff --git a/contrib/mitm-ui/README.md b/contrib/mitm-ui/README.md
deleted file mode 100644
index 1ec8dd4..0000000
--- a/contrib/mitm-ui/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Scripts for PolyGerrit local development against prod using MitmProxy.
-
-## Installation (OSX)
-
-1. Install Docker from http://docker.com
-2. Start the proxy and create a new proxied browser instance
-   ```
-   cd ~/gerrit
-   ~/mitm-gerrit/mitm-serve-app-dev.sh
-   ```
-3. Make sure that the browser uses the proxy provided by the command line,
-   e.g. if you are a Googler check that the BeyondCorp extension uses the
-   "System/Alternative" proxy.
-4. Install MITM certificates
-   - Open http://mitm.it in the proxied browser window
-   - Follow the instructions to install MITM certs
-
-## Usage
-
-### Add or replace a single plugin containing static content
-
-To develop unminified plugin that loads multiple files, use this.
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-single-plugin.sh ./path/to/static/plugin.html
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. plugin.html and ./path/to/static/* will be served
-
-### Add or replace a minified plugin for *.googlesource.com
-
-This flow assumes no additional .html/.js are needed, i.e. the plugin is a single file.
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-plugins.sh ./path/to/plugin.html,./maybe/one/more.js
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. plugin.html and more.js are served
-
-### Force or replace default site theme for *.googlesource.com
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-theme.sh ./path/to/theme.html
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. Default site themes are enabled.
-4. Local `theme.html` content replaces `/static/gerrit-theme.html`
-5. `/static/*` URLs are served from local theme directory, i.e. `./path/to/`
-
-### Serve uncompiled PolyGerrit
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   cd ~/gerrit
-   ~/mitm-gerrit/mitm-serve-app-dev.sh
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. Instead of prod UI (gr-app.html, gr-app.js), local source files will be served
diff --git a/contrib/mitm-ui/add-header.py b/contrib/mitm-ui/add-header.py
deleted file mode 100644
index f9b2b12..0000000
--- a/contrib/mitm-ui/add-header.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# mitmdump -s add-header.py
-def response(flow):
-    if flow.request.host == 'gerrit-review.googlesource.com' and flow.request.path == "/c/92000?1":
-        #flow.response.headers['any'] = '<meta.rdf>; rel=meta'
-        flow.response.headers['Link'] = '</changes/98000/detail?O=11640c>;rel="preload";crossorigin;'
diff --git a/contrib/mitm-ui/dev-chrome.sh b/contrib/mitm-ui/dev-chrome.sh
deleted file mode 100755
index adcb296..0000000
--- a/contrib/mitm-ui/dev-chrome.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-if [[ "$OSTYPE" != "darwin"* ]]; then
-    echo Only works on OSX.
-    exit 1
-fi
-
-/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=${HOME}/devchrome --proxy-server="127.0.0.1:8888"
diff --git a/contrib/mitm-ui/force-version.py b/contrib/mitm-ui/force-version.py
deleted file mode 100644
index a69c885..0000000
--- a/contrib/mitm-ui/force-version.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# mitmdump -q -p 8888 -s "force-version.py --version $1"
-# Request URL is not changed, only the response context
-from mitmproxy import http
-import argparse
-import re
-
-class Server:
-    def __init__(self, version):
-        self.version = version
-
-    def request(self, flow: http.HTTPFlow) -> None:
-        if "gr-app." in flow.request.pretty_url:
-            flow.request.url = re.sub(
-                r"polygerrit_ui/([\d.]+)/elements",
-                "polygerrit_ui/" + self.version + "/elements",
-                flow.request.url)
-
-def start():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--version", type=str, help="Rapid release version, e.g. 432.0")
-    args = parser.parse_args()
-    return Server(args.version)
diff --git a/contrib/mitm-ui/mitm-docker.sh b/contrib/mitm-ui/mitm-docker.sh
deleted file mode 100755
index a1206f7..0000000
--- a/contrib/mitm-ui/mitm-docker.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-
-extra_volume='/tmp:/tmp'
-
-POSITIONAL=()
-while [[ $# -gt 0 ]]
-do
-key="$1"
-
-case $key in
-    -v|--volume)
-    extra_volume="$2"
-    shift # past argument
-    shift # past value
-    ;;
-    *)    # unknown option
-    POSITIONAL+=("$1") # save it in an array for later
-    shift # past argument
-    ;;
-esac
-done
-set -- "${POSITIONAL[@]}" # restore positional parameters
-
-if [[ -z "$1" ]]; then
-    echo This is a runner for higher-level scripts, e.g. mitm-serve-app-dev.sh
-    echo Alternatively, pass mitmproxy script from the same dir as a parameter, e.g. serve-app-dev.py
-    exit 1
-fi
-
-gerrit_dir=$(pwd)
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-CMD="${mitm_dir}/$1"
-
-docker run --rm -it \
-       -v ~/.mitmproxy:/home/mitmproxy/.mitmproxy \
-       -v ${mitm_dir}:${mitm_dir} \
-       -v ${gerrit_dir}:${gerrit_dir} \
-       -v ${gerrit_dir}/bazel-out:${gerrit_dir}/bazel-out \
-       -v ${extra_volume} \
-       -p 8888:8888 \
-       mitmproxy/mitmproxy:2.0.2 \
-       mitmdump -q -p 8888 -s "${CMD}"
diff --git a/contrib/mitm-ui/mitm-plugins.sh b/contrib/mitm-ui/mitm-plugins.sh
deleted file mode 100755
index fc542bb..0000000
--- a/contrib/mitm-ui/mitm-plugins.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script injects plugins for *.googlesource.com.
-    echo Provide plugin paths, comma-separated, as a parameter.
-    echo This script assumes files do not have dependencies, i.e. minified.
-    exit 1
-fi
-
-realpath() {
-    [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
-}
-
-join () {
-  local IFS="$1"
-  shift
-  echo "$*"
-}
-
-plugins=$1
-plugin_paths=()
-for plugin in $(echo ${plugins} | sed "s/,/ /g")
-do
-    plugin_paths+=($(realpath ${plugin}))
-done
-
-absolute_plugin_paths=$(join , "${plugin_paths[@]}")
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-${mitm_dir}/dev-chrome.sh &
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/mitm-docker.sh \
-           "serve-app-dev.py \
-           --plugins ${absolute_plugin_paths} \
-           --strip_assets \
-           --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-serve-app-dev.sh b/contrib/mitm-ui/mitm-serve-app-dev.sh
deleted file mode 100755
index d4c72cc..0000000
--- a/contrib/mitm-ui/mitm-serve-app-dev.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-workspace="./WORKSPACE"
-if [[ ! -f ${workspace} ]] || [[ ! $(head -n 1 ${workspace}) == *"gerrit"* ]]; then
-    echo Please change to cloned Gerrit repo from https://gerrit.googlesource.com/gerrit/
-    exit 1
-fi
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/dev-chrome.sh &
-
-${mitm_dir}/mitm-docker.sh "serve-app-dev.py --app $(pwd)/polygerrit-ui/app/ --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-single-plugin.sh b/contrib/mitm-ui/mitm-single-plugin.sh
deleted file mode 100755
index 8958229..0000000
--- a/contrib/mitm-ui/mitm-single-plugin.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script serves one plugin with the rest of static content.
-    echo Provide path to index plugin file, e.g. buildbucket.html for buildbucket plugin
-    exit 1
-fi
-
-realpath() {
-  OURPWD=$PWD
-  cd "$(dirname "$1")"
-  LINK=$(basename "$1")
-  while [ -L "$LINK" ]; do
-      LINK=$(readlink "$LINK")
-      cd "$(dirname "$LINK")"
-      LINK="$(basename "$1")"
-  done
-  REAL_DIR=`pwd -P`
-  RESULT=$REAL_DIR/$LINK
-  cd "$OURPWD"
-  echo "$RESULT"
-}
-
-plugin=$(realpath $1)
-plugin_root=$(dirname ${plugin})
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-${mitm_dir}/dev-chrome.sh &
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/mitm-docker.sh -v ${plugin_root}:${plugin_root} \
-           "serve-app-dev.py \
-           --plugins ${plugin} \
-           --strip_assets \
-           --plugin_root ${plugin_root}  \
-           --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-theme.sh b/contrib/mitm-ui/mitm-theme.sh
deleted file mode 100755
index 9290235..0000000
--- a/contrib/mitm-ui/mitm-theme.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script forces or replaces default site theme on *.googlesource.com
-    echo Provide path to the theme.html as a parameter.
-    exit 1
-fi
-
-realpath() {
-  OURPWD=$PWD
-  cd "$(dirname "$1")"
-  LINK=$(basename "$1")
-  while [ -L "$LINK" ]; do
-      LINK=$(readlink "$LINK")
-      cd "$(dirname "$LINK")"
-      LINK="$(basename "$1")"
-  done
-  REAL_DIR=`pwd -P`
-  RESULT=$REAL_DIR/$LINK
-  cd "$OURPWD"
-  echo "$RESULT"
-}
-
-theme=$(realpath "$1")
-theme_dir=$(dirname "${theme}")
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-"${mitm_dir}"/dev-chrome.sh &
-
-"${mitm_dir}"/mitm-docker.sh -v "${theme_dir}":"${theme_dir}" "serve-app-dev.py --strip_assets --theme \"${theme}\""
diff --git a/contrib/mitm-ui/serve-app-dev.py b/contrib/mitm-ui/serve-app-dev.py
deleted file mode 100644
index cdf7bfc..0000000
--- a/contrib/mitm-ui/serve-app-dev.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# 1. install and setup mitmproxy v2.0.2: https://mitmproxy.readthedocs.io/en/v2.0.2/install.html
-#   (In case of python versions trouble, use https://www.anaconda.com/)
-# 2. mitmdump -q -s -p 8888 \
-#   "serve-app-dev.py --app /path/to/polygerrit-ui/app/"
-# 3. start Chrome with --proxy-server="127.0.0.1:8888" --user-data-dir=/tmp/devchrome
-# 4. open, say, gerrit-review.googlesource.com. Or chromium-review.googlesource.com. Any.
-# 5. uncompiled source files are served and you can log in, too.
-# 6. enjoy!
-#
-# P.S. For replacing plugins, use --plugins or --plugin_root
-#
-# --plugin takes comma-separated list of plugins to add or replace.
-#
-# Example: Adding a new plugin to the server response:
-# --plugins ~/gerrit-testsite/plugins/myplugin.html
-#
-# Example: Replace all matching plugins with local versions:
-# --plugins ~/gerrit-testsite/plugins/
-# Following files will be served if they exist for /plugins/tricium/static/tricium.html:
-#  ~/gerrit-testsite/plugins/tricium.html
-#  ~/gerrit-testsite/plugins/tricium/static/tricium.html
-#
-# --assets takes assets bundle.html, expecting rest of the assets files to be in the same folder
-#
-# Example:
-#  --assets ~/gerrit-testsite/assets/a3be19f.html
-#
-
-from mitmproxy import http
-from mitmproxy.script import concurrent
-import argparse
-import json
-import mimetypes
-import os.path
-import re
-import zipfile
-
-class Server:
-    def __init__(self, devpath, components, plugins, pluginroot, assets, strip_assets, theme):
-        if devpath:
-            print("Serving app from " + devpath)
-        if components:
-            print("Serving components from " + components)
-        if pluginroot:
-            print("Serving plugins from " + pluginroot)
-        if assets:
-            self.assets_root, self.assets_file = os.path.split(assets)
-            print("Assets: using " + self.assets_file + " from " + self.assets_root)
-        else:
-            self.assets_root = None
-        if plugins:
-            self.plugins = {path.split("/")[-1:][0]: path for path in map(expandpath, plugins.split(","))}
-            for filename, path in self.plugins.items():
-                print("Serving " + filename + " from " + path)
-        else:
-            self.plugins = {}
-        self.devpath = devpath
-        self.components = components
-        self.pluginroot = pluginroot
-        self.strip_assets = strip_assets
-        self.theme = theme
-
-    def readfile(self, path):
-        with open(path, 'rb') as contentfile:
-            return contentfile.read()
-
-@concurrent
-def response(flow: http.HTTPFlow) -> None:
-    if server.strip_assets:
-        assets_bundle = 'googlesource.com/polygerrit_assets'
-        assets_pos = flow.response.text.find(assets_bundle)
-        if assets_pos != -1:
-            t = flow.response.text
-            flow.response.text = t[:t.rfind('<', 0, assets_pos)] + t[t.find('>', assets_pos) + 1:]
-            return
-
-    if server.assets_root:
-        marker = 'webcomponents-lite.js"></script>'
-        pos = flow.response.text.find(marker)
-        if pos != -1:
-            pos += len(marker)
-            flow.response.text = ''.join([
-                flow.response.text[:pos],
-                '<link rel="import" href="/gerrit_assets/123.0/' + server.assets_file + '">',
-                flow.response.text[pos:]
-            ])
-
-        assets_prefix = "/gerrit_assets/123.0/"
-        if flow.request.path.startswith(assets_prefix):
-            assets_file = flow.request.path[len(assets_prefix):]
-            flow.response.content = server.readfile(server.assets_root + '/' + assets_file)
-            flow.response.status_code = 200
-            if assets_file.endswith('.js'):
-                flow.response.headers['Content-type'] = 'text/javascript'
-            return
-    m = re.match(".+polygerrit_ui/\d+\.\d+/(.+)", flow.request.path)
-    pluginmatch = re.match("^/plugins/(.+)", flow.request.path)
-    localfile = ""
-    content = ""
-    if flow.request.path == "/config/server/info":
-        config = json.loads(flow.response.content[5:].decode('utf8'))
-        if server.theme:
-            config['default_theme'] = '/static/gerrit-theme.html'
-        for filename, path in server.plugins.items():
-            pluginname = filename.split(".")[0]
-            payload = config["plugin"]["js_resource_paths" if filename.endswith(".js") else "html_resource_paths"]
-            if list(filter(lambda url: filename in url, payload)):
-                continue
-            payload.append("plugins/" + pluginname + "/static/" + filename)
-        flow.response.content = str.encode(")]}'\n" + json.dumps(config))
-    if m is not None:
-        filepath = m.groups()[0]
-        if (filepath.startswith("bower_components/")):
-            with zipfile.ZipFile(server.components + "test_components.zip") as bower_zip:
-                content = bower_zip.read(filepath)
-        localfile = server.devpath + filepath
-    elif pluginmatch is not None:
-        pluginfile = flow.request.path_components[-1]
-        if server.plugins and pluginfile in server.plugins:
-            if os.path.isfile(server.plugins[pluginfile]):
-                localfile = server.plugins[pluginfile]
-            else:
-                print("Can't find file " + server.plugins[pluginfile] + " for " + flow.request.path)
-        elif server.pluginroot:
-            pluginurl = pluginmatch.groups()[0]
-            if os.path.isfile(server.pluginroot + pluginfile):
-                localfile = server.pluginroot + pluginfile
-            elif os.path.isfile(server.pluginroot + pluginurl):
-                localfile = server.pluginroot + pluginurl
-
-    if server.theme:
-        if flow.request.path.endswith('/gerrit-theme.html'):
-            localfile = server.theme
-        else:
-            match = re.match("^/static(/[\w\.]+)$", flow.request.path)
-            if match is not None:
-                localfile = os.path.dirname(server.theme) + match.group(1)
-
-    if localfile and os.path.isfile(localfile):
-        if pluginmatch is not None:
-            print("Serving " + flow.request.path + " from " + localfile)
-        content = server.readfile(localfile)
-
-    if content:
-        flow.response.content = content
-        flow.response.status_code = 200
-        localtype = mimetypes.guess_type(localfile)
-        if localtype and localtype[0]:
-            flow.response.headers['Content-type'] = localtype[0]
-
-def expandpath(path):
-    return os.path.realpath(os.path.expanduser(path))
-
-parser = argparse.ArgumentParser()
-parser.add_argument("--app", type=str, default="", help="Path to /polygerrit-ui/app/")
-parser.add_argument("--components", type=str, default="", help="Path to test_components.zip")
-parser.add_argument("--plugins", type=str, default="", help="Comma-separated list of plugin files to add/replace")
-parser.add_argument("--plugin_root", type=str, default="", help="Path containing individual plugin files to replace")
-parser.add_argument("--assets", type=str, default="", help="Path containing assets file to import.")
-parser.add_argument("--strip_assets", action="store_true", help="Strip plugin bundles from the response.")
-parser.add_argument("--theme", default="", type=str, help="Path to the default site theme to be used.")
-args = parser.parse_args()
-server = Server(expandpath(args.app) + '/',
-                expandpath(args.components) + '/',
-                args.plugins,
-                expandpath(args.plugin_root) + '/',
-                args.assets and expandpath(args.assets),
-                args.strip_assets,
-                expandpath(args.theme))
diff --git a/contrib/mitm-ui/serve-app-locally.py b/contrib/mitm-ui/serve-app-locally.py
deleted file mode 100644
index 636c684..0000000
--- a/contrib/mitm-ui/serve-app-locally.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# bazel build polygerrit-ui/app:gr-app
-# mitmdump -s "serve-app-locally.py ~/gerrit/bazel-bin/polygerrit-ui/app"
-from mitmproxy import http
-import argparse
-import os
-import zipfile
-
-class Server:
-    def __init__(self, bundle):
-        self.bundle = bundle
-        self.bundlemtime = 0
-        self.files = {
-            'polygerrit_ui/elements/gr-app.js': '',
-            'polygerrit_ui/elements/gr-app.html': '',
-            'polygerrit_ui/styles/main.css': '',
-        }
-        self.read_files()
-
-    def read_files(self):
-        if not os.path.isfile(self.bundle):
-            print("bundle not found!")
-            return
-        mtime = os.stat(self.bundle).st_mtime
-        if mtime <= self.bundlemtime:
-            return
-        self.bundlemtime = mtime
-        with zipfile.ZipFile(self.bundle) as z:
-            for fname in self.files:
-                print('Reading new content for ' + fname)
-                with z.open(fname, 'r') as content_file:
-                    self.files[fname] = content_file.read()
-
-    def response(self, flow: http.HTTPFlow) -> None:
-        self.read_files()
-        for name in self.files:
-            if name.rsplit('/', 1)[1] in flow.request.pretty_url:
-                flow.response.content = self.files[name]
-
-def expandpath(path):
-    return os.path.expanduser(path)
-
-def start():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("bundle", type=str)
-    args = parser.parse_args()
-    return Server(expandpath(args.bundle))
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 7edb43a..fd61aa5 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -644,6 +644,14 @@
     return result;
   }
 
+  protected PushOneCommit.Result createChange(TestRepository<InMemoryRepository> repo)
+      throws Exception {
+    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
+    PushOneCommit.Result result = push.to("refs/for/master");
+    result.assertOkStatus();
+    return result;
+  }
+
   protected PushOneCommit.Result createMergeCommitChange(String ref) throws Exception {
     return createMergeCommitChange(ref, "foo");
   }
diff --git a/java/com/google/gerrit/acceptance/BUILD b/java/com/google/gerrit/acceptance/BUILD
index 38a9035..b68130b 100644
--- a/java/com/google/gerrit/acceptance/BUILD
+++ b/java/com/google/gerrit/acceptance/BUILD
@@ -79,6 +79,7 @@
     ),
     exported_deps = [
         ":function",
+        "//java/com/google/gerrit/acceptance/config",
         "//java/com/google/gerrit/acceptance/testsuite/project",
         "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/gpg",
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 678bc31..af8af90 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -25,6 +25,11 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.acceptance.config.ConfigAnnotationParser;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfigs;
+import com.google.gerrit.acceptance.config.GlobalPluginConfig;
+import com.google.gerrit.acceptance.config.GlobalPluginConfigs;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperationsImpl;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
@@ -264,7 +269,7 @@
 
   private static final ImmutableMap<String, Level> LOG_LEVELS =
       ImmutableMap.<String, Level>builder()
-          .put("com.google.gerrit", Level.DEBUG)
+          .put("com.google.gerrit", Level.INFO)
 
           // Silence non-critical messages from MINA SSHD.
           .put("org.apache.mina", Level.WARN)
@@ -558,8 +563,8 @@
     cfg.setInt("sshd", null, "commandStartThreads", 1);
     cfg.setInt("receive", null, "threadPoolSize", 1);
     cfg.setInt("index", null, "threads", 1);
-    if (cfg.getString("index", null, "reindexAfterRefUpdate") == null) {
-      cfg.setBoolean("index", null, "reindexAfterRefUpdate", false);
+    if (cfg.getString("index", "change", "indexMergeable") == null) {
+      cfg.setBoolean("index", "change", "indexMergeable", false);
     }
   }
 
diff --git a/java/com/google/gerrit/acceptance/InProcessProtocol.java b/java/com/google/gerrit/acceptance/InProcessProtocol.java
index ce2eb46..8a46d57 100644
--- a/java/com/google/gerrit/acceptance/InProcessProtocol.java
+++ b/java/com/google/gerrit/acceptance/InProcessProtocol.java
@@ -342,7 +342,7 @@
             ImmutableList.<PostReceiveHook>builder()
                 .add(
                     (pack, commands) -> {
-                      if (affectsSize(pack, commands)) {
+                      if (affectsSize(pack)) {
                         try {
                           quotaBackend
                               .user(identifiedUser)
diff --git a/java/com/google/gerrit/acceptance/config/BUILD b/java/com/google/gerrit/acceptance/config/BUILD
new file mode 100644
index 0000000..a8ccc1f
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/BUILD
@@ -0,0 +1,15 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(default_testonly = 1)
+
+java_library(
+    name = "config",
+    srcs = glob(["*.java"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        "//lib:guava",
+        "//lib:jgit",
+        "//lib/auto:auto-value",
+        "//lib/auto:auto-value-annotations",
+    ],
+)
diff --git a/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java b/java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java
similarity index 89%
rename from java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
rename to java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java
index 0a1d765..24a2117 100644
--- a/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
+++ b/java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance;
+package com.google.gerrit.acceptance.config;
 
 import com.google.auto.value.AutoAnnotation;
 import com.google.common.base.Splitter;
@@ -24,10 +24,10 @@
 import java.util.Map;
 import org.eclipse.jgit.lib.Config;
 
-class ConfigAnnotationParser {
+public class ConfigAnnotationParser {
   private static Splitter splitter = Splitter.on(".").trimResults();
 
-  static Config parse(Config base, GerritConfigs annotation) {
+  public static Config parse(Config base, GerritConfigs annotation) {
     if (annotation == null) {
       return null;
     }
@@ -39,33 +39,13 @@
     return cfg;
   }
 
-  static Config parse(Config base, GerritConfig annotation) {
+  public static Config parse(Config base, GerritConfig annotation) {
     Config cfg = new Config(base);
     parseAnnotation(cfg, annotation);
     return cfg;
   }
 
-  private static GerritConfig toGerritConfig(GlobalPluginConfig annotation) {
-    return newGerritConfig(annotation.name(), annotation.value(), annotation.values());
-  }
-
-  @AutoAnnotation
-  private static GerritConfig newGerritConfig(String name, String value, String[] values) {
-    return new AutoAnnotation_ConfigAnnotationParser_newGerritConfig(name, value, values);
-  }
-
-  static Map<String, Config> parse(GlobalPluginConfig annotation) {
-    if (annotation == null) {
-      return null;
-    }
-    Map<String, Config> result = new HashMap<>();
-    Config cfg = new Config();
-    parseAnnotation(cfg, toGerritConfig(annotation));
-    result.put(annotation.pluginName(), cfg);
-    return result;
-  }
-
-  static Map<String, Config> parse(GlobalPluginConfigs annotation) {
+  public static Map<String, Config> parse(GlobalPluginConfigs annotation) {
     if (annotation == null || annotation.value().length < 1) {
       return null;
     }
@@ -87,6 +67,26 @@
     return result;
   }
 
+  public static Map<String, Config> parse(GlobalPluginConfig annotation) {
+    if (annotation == null) {
+      return null;
+    }
+    Map<String, Config> result = new HashMap<>();
+    Config cfg = new Config();
+    parseAnnotation(cfg, toGerritConfig(annotation));
+    result.put(annotation.pluginName(), cfg);
+    return result;
+  }
+
+  private static GerritConfig toGerritConfig(GlobalPluginConfig annotation) {
+    return newGerritConfig(annotation.name(), annotation.value(), annotation.values());
+  }
+
+  @AutoAnnotation
+  private static GerritConfig newGerritConfig(String name, String value, String[] values) {
+    return new AutoAnnotation_ConfigAnnotationParser_newGerritConfig(name, value, values);
+  }
+
   private static void parseAnnotation(Config cfg, GerritConfig c) {
     ArrayList<String> l = Lists.newArrayList(splitter.split(c.name()));
     if (l.size() == 2) {
diff --git a/java/com/google/gerrit/acceptance/GerritConfig.java b/java/com/google/gerrit/acceptance/config/GerritConfig.java
similarity index 96%
rename from java/com/google/gerrit/acceptance/GerritConfig.java
rename to java/com/google/gerrit/acceptance/config/GerritConfig.java
index fe0c628..26be2d4 100644
--- a/java/com/google/gerrit/acceptance/GerritConfig.java
+++ b/java/com/google/gerrit/acceptance/config/GerritConfig.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance;
+package com.google.gerrit.acceptance.config;
 
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
diff --git a/java/com/google/gerrit/acceptance/GerritConfigs.java b/java/com/google/gerrit/acceptance/config/GerritConfigs.java
similarity index 94%
rename from java/com/google/gerrit/acceptance/GerritConfigs.java
rename to java/com/google/gerrit/acceptance/config/GerritConfigs.java
index e0f9d4a..0127ace 100644
--- a/java/com/google/gerrit/acceptance/GerritConfigs.java
+++ b/java/com/google/gerrit/acceptance/config/GerritConfigs.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance;
+package com.google.gerrit.acceptance.config;
 
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
diff --git a/java/com/google/gerrit/acceptance/GlobalPluginConfig.java b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
similarity index 96%
rename from java/com/google/gerrit/acceptance/GlobalPluginConfig.java
rename to java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
index 43477ae..ae88e37 100644
--- a/java/com/google/gerrit/acceptance/GlobalPluginConfig.java
+++ b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance;
+package com.google.gerrit.acceptance.config;
 
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
diff --git a/java/com/google/gerrit/acceptance/GlobalPluginConfigs.java b/java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java
similarity index 95%
rename from java/com/google/gerrit/acceptance/GlobalPluginConfigs.java
rename to java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java
index dfcf955..e53e5ba 100644
--- a/java/com/google/gerrit/acceptance/GlobalPluginConfigs.java
+++ b/java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance;
+package com.google.gerrit.acceptance.config;
 
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index fbdc383..864839a 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -87,6 +87,10 @@
   protected static final String SEARCH = "_search";
   protected static final String SETTINGS = "settings";
 
+  protected static byte[] decodeBase64(String base64String) {
+    return Base64.decodeBase64(base64String);
+  }
+
   protected static <T> List<T> decodeProtos(
       JsonObject doc, String fieldName, ProtoConverter<?, T> converter) {
     JsonArray field = doc.getAsJsonArray(fieldName);
@@ -94,8 +98,8 @@
       return null;
     }
     return Streams.stream(field)
-        .map(JsonElement::toString)
-        .map(Base64::decodeBase64)
+        .map(JsonElement::getAsString)
+        .map(AbstractElasticIndex::decodeBase64)
         .map(bytes -> parseProtoFrom(bytes, converter))
         .collect(toImmutableList());
   }
diff --git a/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
index a06f90f..c3e3264 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -74,7 +75,7 @@
   public void replace(AccountState as) {
     BulkRequest bulk =
         new IndexRequest(getId(as), indexName, type, client.adapter())
-            .add(new UpdateRequest<>(schema, as));
+            .add(new UpdateRequest<>(schema, as, ImmutableSet.of()));
 
     String uri = getURI(type, BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index 6151de2..084c2ec 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -18,11 +18,11 @@
 import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Objects.requireNonNull;
-import static org.apache.commons.codec.binary.Base64.decodeBase64;
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
@@ -49,6 +49,7 @@
 import com.google.gerrit.server.ReviewerByEmailSet;
 import com.google.gerrit.server.ReviewerSet;
 import com.google.gerrit.server.StarredChangesUtil;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.index.IndexUtils;
 import com.google.gerrit.server.index.change.ChangeField;
@@ -65,8 +66,8 @@
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.http.HttpStatus;
+import org.eclipse.jgit.lib.Config;
 import org.elasticsearch.client.Response;
 
 /** Secondary index implementation using Elasticsearch. */
@@ -93,6 +94,7 @@
   private final ChangeData.Factory changeDataFactory;
   private final Schema<ChangeData> schema;
   private final FieldDef<ChangeData, ?> idField;
+  private final ImmutableSet<String> skipFields;
 
   @Inject
   ElasticChangeIndex(
@@ -100,6 +102,7 @@
       ChangeData.Factory changeDataFactory,
       SitePaths sitePaths,
       ElasticRestClientProvider clientBuilder,
+      @GerritServerConfig Config gerritConfig,
       @Assisted Schema<ChangeData> schema) {
     super(cfg, sitePaths, schema, clientBuilder, CHANGES);
     this.changeDataFactory = changeDataFactory;
@@ -107,6 +110,10 @@
     this.mapping = new ChangeMapping(schema, client.adapter());
     this.idField =
         this.schema.useLegacyNumericFields() ? ChangeField.LEGACY_ID : ChangeField.LEGACY_ID_STR;
+    this.skipFields =
+        gerritConfig.getBoolean("index", "change", "indexMergeable", true)
+            ? ImmutableSet.of()
+            : ImmutableSet.of(ChangeField.MERGEABLE.getName());
   }
 
   @Override
@@ -125,7 +132,7 @@
     ElasticQueryAdapter adapter = client.adapter();
     BulkRequest bulk =
         new IndexRequest(getId(cd), indexName, adapter.getType(insertIndex), adapter)
-            .add(new UpdateRequest<>(schema, cd));
+            .add(new UpdateRequest<>(schema, cd, skipFields));
     if (adapter.deleteToReplace()) {
       bulk.add(new DeleteRequest(cd.getId().toString(), indexName, deleteIndex, adapter));
     }
@@ -219,7 +226,7 @@
 
     ChangeData cd =
         changeDataFactory.create(
-            parseProtoFrom(Base64.decodeBase64(c.getAsString()), ChangeProtoConverter.INSTANCE));
+            parseProtoFrom(decodeBase64(c.getAsString()), ChangeProtoConverter.INSTANCE));
 
     // Any decoding that is done here must also be done in {@link LuceneChangeIndex}.
 
@@ -265,7 +272,7 @@
 
     // Mergeable.
     JsonElement mergeableElement = source.get(ChangeField.MERGEABLE.getName());
-    if (mergeableElement != null) {
+    if (mergeableElement != null && !skipFields.contains(ChangeField.MERGEABLE.getName())) {
       String mergeable = mergeableElement.getAsString();
       if ("1".equals(mergeable)) {
         cd.setMergeable(true);
@@ -403,7 +410,7 @@
   private Iterable<byte[]> getByteArray(JsonObject source, String name) {
     JsonElement element = source.get(name);
     return element != null
-        ? Iterables.transform(element.getAsJsonArray(), e -> Base64.decodeBase64(e.getAsString()))
+        ? Iterables.transform(element.getAsJsonArray(), e -> decodeBase64(e.getAsString()))
         : Collections.emptyList();
   }
 
@@ -415,7 +422,7 @@
     }
     ChangeField.parseSubmitRecords(
         FluentIterable.from(records)
-            .transform(i -> new String(decodeBase64(i.toString()), UTF_8))
+            .transform(i -> new String(decodeBase64(i.getAsString()), UTF_8))
             .toList(),
         opts,
         out);
diff --git a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
index c215132..ce2025f 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -74,7 +75,7 @@
   public void replace(InternalGroup group) {
     BulkRequest bulk =
         new IndexRequest(getId(group), indexName, type, client.adapter())
-            .add(new UpdateRequest<>(schema, group));
+            .add(new UpdateRequest<>(schema, group, ImmutableSet.of()));
 
     String uri = getURI(type, BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
diff --git a/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
index 29f8507..b636706 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -74,7 +75,7 @@
   public void replace(ProjectData projectState) {
     BulkRequest bulk =
         new IndexRequest(projectState.getProject().getName(), indexName, type, client.adapter())
-            .add(new UpdateRequest<>(schema, projectState));
+            .add(new UpdateRequest<>(schema, projectState, ImmutableSet.of()));
 
     String uri = getURI(type, BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
diff --git a/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java b/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
index 2f0bd01..196b8d6 100644
--- a/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
+++ b/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
@@ -16,6 +16,7 @@
 
 import static java.util.stream.Collectors.toList;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Streams;
 import com.google.gerrit.elasticsearch.builders.XContentBuilder;
@@ -27,17 +28,19 @@
 
   private final Schema<V> schema;
   private final V v;
+  private final ImmutableSet<String> skipFields;
 
-  public UpdateRequest(Schema<V> schema, V v) {
+  public UpdateRequest(Schema<V> schema, V v, ImmutableSet<String> skipFields) {
     this.schema = schema;
     this.v = v;
+    this.skipFields = skipFields;
   }
 
   @Override
   protected String getRequest() {
     try (XContentBuilder closeable = new XContentBuilder()) {
       XContentBuilder builder = closeable.startObject();
-      for (Values<V> values : schema.buildFields(v)) {
+      for (Values<V> values : schema.buildFields(v, skipFields)) {
         String name = values.getField().getName();
         if (values.getField().isRepeatable()) {
           builder.field(name, Streams.stream(values.getValues()).collect(toList()));
diff --git a/java/com/google/gerrit/entities/Comment.java b/java/com/google/gerrit/entities/Comment.java
index 65c642c..55d739a 100644
--- a/java/com/google/gerrit/entities/Comment.java
+++ b/java/com/google/gerrit/entities/Comment.java
@@ -229,12 +229,6 @@
   public String serverId;
   public boolean unresolved;
 
-  /**
-   * Whether the comment was parsed from a JSON representation (false) or the legacy custom notes
-   * format (true).
-   */
-  public transient boolean legacyFormat;
-
   public Comment(Comment c) {
     this(
         new Key(c.key),
diff --git a/java/com/google/gerrit/extensions/api/changes/FileApi.java b/java/com/google/gerrit/extensions/api/changes/FileApi.java
index 39cf2b7..8d9b2d5 100644
--- a/java/com/google/gerrit/extensions/api/changes/FileApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/FileApi.java
@@ -15,10 +15,12 @@
 package com.google.gerrit.extensions.api.changes;
 
 import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
+import com.google.gerrit.extensions.common.BlameInfo;
 import com.google.gerrit.extensions.common.DiffInfo;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.NotImplementedException;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import java.util.List;
 import java.util.OptionalInt;
 
 public interface FileApi {
@@ -42,6 +44,12 @@
   /** Set the file reviewed or not reviewed */
   void setReviewed(boolean reviewed) throws RestApiException;
 
+  /**
+   * Creates a request to retrieve the blame information. On the returned request formatting options
+   * for the blame request can be set.
+   */
+  BlameRequest blameRequest() throws RestApiException;
+
   abstract class DiffRequest {
     private String base;
     private Integer context;
@@ -97,6 +105,21 @@
     }
   }
 
+  abstract class BlameRequest {
+    private boolean forBase;
+
+    public abstract List<BlameInfo> get() throws RestApiException;
+
+    public BlameRequest forBase(boolean forBase) {
+      this.forBase = forBase;
+      return this;
+    }
+
+    public boolean isForBase() {
+      return forBase;
+    }
+  }
+
   /**
    * A default implementation which allows source compatibility when adding new methods to the
    * interface.
@@ -131,5 +154,10 @@
     public void setReviewed(boolean reviewed) throws RestApiException {
       throw new NotImplementedException();
     }
+
+    @Override
+    public BlameRequest blameRequest() throws RestApiException {
+      throw new NotImplementedException();
+    }
   }
 }
diff --git a/java/com/google/gerrit/extensions/api/projects/ProjectApi.java b/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
index 6d02ec4..9873995 100644
--- a/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
+++ b/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
@@ -18,6 +18,7 @@
 import com.google.gerrit.extensions.api.access.ProjectAccessInput;
 import com.google.gerrit.extensions.api.config.AccessCheckInfo;
 import com.google.gerrit.extensions.api.config.AccessCheckInput;
+import com.google.gerrit.extensions.common.BatchLabelInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.LabelDefinitionInfo;
 import com.google.gerrit.extensions.common.ProjectInfo;
@@ -221,6 +222,13 @@
   LabelApi label(String labelName) throws RestApiException;
 
   /**
+   * Adds, updates and deletes label definitions in a batch.
+   *
+   * @param input input that describes additions, updates and deletions of label definitions
+   */
+  void labels(BatchLabelInput input) throws RestApiException;
+
+  /**
    * A default implementation which allows source compatibility when adding new methods to the
    * interface.
    */
@@ -404,5 +412,10 @@
     public LabelApi label(String labelName) throws RestApiException {
       throw new NotImplementedException();
     }
+
+    @Override
+    public void labels(BatchLabelInput input) throws RestApiException {
+      throw new NotImplementedException();
+    }
   }
 }
diff --git a/java/com/google/gerrit/extensions/common/BatchLabelInput.java b/java/com/google/gerrit/extensions/common/BatchLabelInput.java
new file mode 100644
index 0000000..eb4c581
--- /dev/null
+++ b/java/com/google/gerrit/extensions/common/BatchLabelInput.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.common;
+
+import java.util.List;
+import java.util.Map;
+
+/** Input for the REST API that describes additions, updates and deletions of label definitions. */
+public class BatchLabelInput {
+  public String commitMessage;
+  public List<String> delete;
+  public List<LabelDefinitionInput> create;
+  public Map<String, LabelDefinitionInput> update;
+}
diff --git a/java/com/google/gerrit/extensions/common/ChangeInfo.java b/java/com/google/gerrit/extensions/common/ChangeInfo.java
index 9a739ef..0d7c5c7 100644
--- a/java/com/google/gerrit/extensions/common/ChangeInfo.java
+++ b/java/com/google/gerrit/extensions/common/ChangeInfo.java
@@ -52,6 +52,7 @@
   public Boolean workInProgress;
   public Boolean hasReviewStarted;
   public Integer revertOf;
+  public String submissionId;
 
   public int _number;
 
diff --git a/java/com/google/gerrit/index/Schema.java b/java/com/google/gerrit/index/Schema.java
index f9f8c48..0aa374b 100644
--- a/java/com/google/gerrit/index/Schema.java
+++ b/java/com/google/gerrit/index/Schema.java
@@ -15,11 +15,12 @@
 package com.google.gerrit.index;
 
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableList.toImmutableList;
 
 import com.google.common.base.MoreObjects;
-import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.flogger.FluentLogger;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -181,12 +182,17 @@
    * <p>Null values are omitted, as are fields which cause errors, which are logged.
    *
    * @param obj input object.
+   * @param skipFields set of field names to skip when indexing the document
    * @return all non-null field values from the object.
    */
-  public final Iterable<Values<T>> buildFields(T obj) {
-    return FluentIterable.from(fields.values())
-        .transform(
+  public final Iterable<Values<T>> buildFields(T obj, ImmutableSet<String> skipFields) {
+    return fields.values().stream()
+        .map(
             f -> {
+              if (skipFields.contains(f.getName())) {
+                return null;
+              }
+
               Object v;
               try {
                 v = f.get(obj);
@@ -203,7 +209,8 @@
                 return new Values<>(f, Collections.singleton(v));
               }
             })
-        .filter(Objects::nonNull);
+        .filter(Objects::nonNull)
+        .collect(toImmutableList());
   }
 
   @Override
diff --git a/java/com/google/gerrit/index/query/QueryProcessor.java b/java/com/google/gerrit/index/query/QueryProcessor.java
index 9501e52..c05516b 100644
--- a/java/com/google/gerrit/index/query/QueryProcessor.java
+++ b/java/com/google/gerrit/index/query/QueryProcessor.java
@@ -18,7 +18,7 @@
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.ImmutableList.toImmutableList;
 import static com.google.common.flogger.LazyArgs.lazy;
-import static java.util.stream.Collectors.toSet;
+import static java.util.stream.Collectors.toList;
 
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
@@ -272,7 +272,7 @@
         ImmutableList<T> matchesList = matches.get(i).toList();
         logger.atFine().log(
             "Matches[%d]:\n%s",
-            i, lazy(() -> matchesList.stream().map(this::formatForLogging).collect(toSet())));
+            i, lazy(() -> matchesList.stream().map(this::formatForLogging).collect(toList())));
         out.add(
             QueryResult.create(
                 queryStrings != null ? queryStrings.get(i) : null,
diff --git a/java/com/google/gerrit/index/query/RangeUtil.java b/java/com/google/gerrit/index/query/RangeUtil.java
index 1f22f36..cfe1929 100644
--- a/java/com/google/gerrit/index/query/RangeUtil.java
+++ b/java/com/google/gerrit/index/query/RangeUtil.java
@@ -106,6 +106,10 @@
         break;
     }
 
+    // Ensure that minValue <= min/max <= maxValue.
+    min = Ints.constrainToRange(min, minValue, maxValue);
+    max = Ints.constrainToRange(max, minValue, maxValue);
+
     return new Range(prefix, min, max);
   }
 
diff --git a/java/com/google/gerrit/lucene/AbstractLuceneIndex.java b/java/com/google/gerrit/lucene/AbstractLuceneIndex.java
index deb3203..5392ab4 100644
--- a/java/com/google/gerrit/lucene/AbstractLuceneIndex.java
+++ b/java/com/google/gerrit/lucene/AbstractLuceneIndex.java
@@ -21,6 +21,7 @@
 import com.google.common.base.Joiner;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Sets;
 import com.google.common.flogger.FluentLogger;
@@ -98,6 +99,7 @@
   private final SitePaths sitePaths;
   private final Directory dir;
   private final String name;
+  private final ImmutableSet<String> skipFields;
   private final ListeningExecutorService writerThread;
   private final IndexWriter writer;
   private final ReferenceManager<IndexSearcher> searcherManager;
@@ -110,6 +112,7 @@
       SitePaths sitePaths,
       Directory dir,
       String name,
+      ImmutableSet<String> skipFields,
       String subIndex,
       GerritIndexWriterConfig writerConfig,
       SearcherFactory searcherFactory)
@@ -118,6 +121,7 @@
     this.sitePaths = sitePaths;
     this.dir = dir;
     this.name = name;
+    this.skipFields = skipFields;
     String index = Joiner.on('_').skipNulls().join(name, subIndex);
     long commitPeriod = writerConfig.getCommitWithinMs();
 
@@ -311,7 +315,7 @@
 
   Document toDocument(V obj) {
     Document result = new Document();
-    for (Values<V> vs : schema.buildFields(obj)) {
+    for (Values<V> vs : schema.buildFields(obj, skipFields)) {
       if (vs.getValues() != null) {
         add(result, vs);
       }
diff --git a/java/com/google/gerrit/lucene/ChangeSubIndex.java b/java/com/google/gerrit/lucene/ChangeSubIndex.java
index fd439f1..e51a91a7 100644
--- a/java/com/google/gerrit/lucene/ChangeSubIndex.java
+++ b/java/com/google/gerrit/lucene/ChangeSubIndex.java
@@ -20,6 +20,7 @@
 import static com.google.gerrit.lucene.LuceneChangeIndex.UPDATED_SORT_FIELD;
 import static com.google.gerrit.server.index.change.ChangeSchemaDefinitions.NAME;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.index.FieldDef;
 import com.google.gerrit.index.QueryOptions;
@@ -48,6 +49,7 @@
       Schema<ChangeData> schema,
       SitePaths sitePaths,
       Path path,
+      ImmutableSet<String> skipFields,
       GerritIndexWriterConfig writerConfig,
       SearcherFactory searcherFactory)
       throws IOException {
@@ -56,6 +58,7 @@
         sitePaths,
         FSDirectory.open(path),
         path.getFileName().toString(),
+        skipFields,
         writerConfig,
         searcherFactory);
   }
@@ -65,10 +68,11 @@
       SitePaths sitePaths,
       Directory dir,
       String subIndex,
+      ImmutableSet<String> skipFields,
       GerritIndexWriterConfig writerConfig,
       SearcherFactory searcherFactory)
       throws IOException {
-    super(schema, sitePaths, dir, NAME, subIndex, writerConfig, searcherFactory);
+    super(schema, sitePaths, dir, NAME, skipFields, subIndex, writerConfig, searcherFactory);
   }
 
   @Override
diff --git a/java/com/google/gerrit/lucene/LuceneAccountIndex.java b/java/com/google/gerrit/lucene/LuceneAccountIndex.java
index efd7ea3..242cffd 100644
--- a/java/com/google/gerrit/lucene/LuceneAccountIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneAccountIndex.java
@@ -20,6 +20,7 @@
 import static com.google.gerrit.server.index.account.AccountField.ID_STR;
 import static com.google.gerrit.server.index.account.AccountField.PREFERRED_EMAIL_EXACT;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.index.FieldDef;
@@ -100,6 +101,7 @@
         sitePaths,
         dir(schema, cfg, sitePaths),
         ACCOUNTS,
+        ImmutableSet.of(),
         null,
         new GerritIndexWriterConfig(cfg, ACCOUNTS),
         new SearcherFactory());
diff --git a/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index 16d66b6..3b277dd 100644
--- a/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -29,6 +29,7 @@
 import com.google.common.collect.Collections2;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.MultimapBuilder;
@@ -167,6 +168,7 @@
   private final String idSortFieldName;
   private final IdTerm idTerm;
   private final ChangeIdExtractor extractor;
+  private final ImmutableSet<String> skipFields;
 
   @Inject
   LuceneChangeIndex(
@@ -179,6 +181,10 @@
     this.executor = executor;
     this.changeDataFactory = changeDataFactory;
     this.schema = schema;
+    this.skipFields =
+        cfg.getBoolean("index", "change", "indexMergeable", true)
+            ? ImmutableSet.of()
+            : ImmutableSet.of(ChangeField.MERGEABLE.getName());
 
     GerritIndexWriterConfig openConfig = new GerritIndexWriterConfig(cfg, "changes_open");
     GerritIndexWriterConfig closedConfig = new GerritIndexWriterConfig(cfg, "changes_closed");
@@ -189,18 +195,40 @@
     if (LuceneIndexModule.isInMemoryTest(cfg)) {
       openIndex =
           new ChangeSubIndex(
-              schema, sitePaths, new RAMDirectory(), "ramOpen", openConfig, searcherFactory);
+              schema,
+              sitePaths,
+              new RAMDirectory(),
+              "ramOpen",
+              skipFields,
+              openConfig,
+              searcherFactory);
       closedIndex =
           new ChangeSubIndex(
-              schema, sitePaths, new RAMDirectory(), "ramClosed", closedConfig, searcherFactory);
+              schema,
+              sitePaths,
+              new RAMDirectory(),
+              "ramClosed",
+              skipFields,
+              closedConfig,
+              searcherFactory);
     } else {
       Path dir = LuceneVersionManager.getDir(sitePaths, CHANGES, schema);
       openIndex =
           new ChangeSubIndex(
-              schema, sitePaths, dir.resolve(CHANGES_OPEN), openConfig, searcherFactory);
+              schema,
+              sitePaths,
+              dir.resolve(CHANGES_OPEN),
+              skipFields,
+              openConfig,
+              searcherFactory);
       closedIndex =
           new ChangeSubIndex(
-              schema, sitePaths, dir.resolve(CHANGES_CLOSED), closedConfig, searcherFactory);
+              schema,
+              sitePaths,
+              dir.resolve(CHANGES_CLOSED),
+              skipFields,
+              closedConfig,
+              searcherFactory);
     }
 
     idField = this.schema.useLegacyNumericFields() ? LEGACY_ID : LEGACY_ID_STR;
@@ -565,7 +593,7 @@
 
   private void decodeMergeable(ListMultimap<String, IndexableField> doc, ChangeData cd) {
     IndexableField f = Iterables.getFirst(doc.get(MERGEABLE_FIELD), null);
-    if (f != null) {
+    if (f != null && !skipFields.contains(MERGEABLE_FIELD)) {
       String mergeable = f.stringValue();
       if ("1".equals(mergeable)) {
         cd.setMergeable(true);
diff --git a/java/com/google/gerrit/lucene/LuceneGroupIndex.java b/java/com/google/gerrit/lucene/LuceneGroupIndex.java
index 99cd40d..3d1d471 100644
--- a/java/com/google/gerrit/lucene/LuceneGroupIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneGroupIndex.java
@@ -17,6 +17,7 @@
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.gerrit.server.index.group.GroupField.UUID;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.index.FieldDef;
@@ -90,6 +91,7 @@
         sitePaths,
         dir(schema, cfg, sitePaths),
         GROUPS,
+        ImmutableSet.of(),
         null,
         new GerritIndexWriterConfig(cfg, GROUPS),
         new SearcherFactory());
diff --git a/java/com/google/gerrit/lucene/LuceneProjectIndex.java b/java/com/google/gerrit/lucene/LuceneProjectIndex.java
index 97454c7..a3a0d9c 100644
--- a/java/com/google/gerrit/lucene/LuceneProjectIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneProjectIndex.java
@@ -17,6 +17,7 @@
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.gerrit.index.project.ProjectField.NAME;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.index.FieldDef;
@@ -90,6 +91,7 @@
         sitePaths,
         dir(schema, cfg, sitePaths),
         PROJECTS,
+        ImmutableSet.of(),
         null,
         new GerritIndexWriterConfig(cfg, PROJECTS),
         new SearcherFactory());
diff --git a/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java b/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
index 9354209..4f9d7e7 100644
--- a/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
+++ b/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
@@ -34,6 +34,10 @@
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -43,16 +47,13 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.continuation.Continuation;
-import org.eclipse.jetty.continuation.ContinuationListener;
-import org.eclipse.jetty.continuation.ContinuationSupport;
 import org.eclipse.jgit.lib.Config;
 
 /**
- * Use Jetty continuations to defer execution until threads are available.
+ * Use AsyncContexts to defer execution until threads are available.
  *
  * <p>We actually schedule a task into the same execution queue as the SSH daemon uses for command
- * execution, and then park the web request in a continuation until an execution thread is
+ * execution, and then park the web request in an AsyncContext until an execution thread is
  * available. This ensures that the overall JVM process doesn't exceed the configured limit on
  * concurrent Git requests.
  *
@@ -61,12 +62,10 @@
  * Jetty's HTTP parser to crash, so we instead block the SSH execution queue thread and ask Jetty to
  * resume processing on the web service thread.
  */
-@SuppressWarnings("deprecation")
 @Singleton
 public class ProjectQoSFilter implements Filter {
-  private static final String ATT_SPACE = ProjectQoSFilter.class.getName();
-  private static final String TASK = ATT_SPACE + "/TASK";
-  private static final String CANCEL = ATT_SPACE + "/CANCEL";
+  private static final String ATT_SPACE = ProjectQoSFilter.class.getName() + "/";
+  private static final String TASK = ATT_SPACE + "TASK";
 
   private static final String FILTER_RE = "^/(.*)/(git-upload-pack|git-receive-pack)$";
   private static final Pattern URI_PATTERN = Pattern.compile(FILTER_RE);
@@ -79,6 +78,59 @@
     }
   }
 
+  public enum RequestState {
+    INITIAL,
+    SUSPENDED,
+    RESUMED,
+    CANCELED,
+    UNEXPECTED;
+
+    private static final String CANCELED_ATT = ATT_SPACE + CANCELED;
+    private static final String SUSPENDED_ATT = ATT_SPACE + SUSPENDED;
+    private static final String RESUMED_ATT = ATT_SPACE + RESUMED;
+
+    private void set(ServletRequest req) {
+      switch (this) {
+        case SUSPENDED:
+          req.setAttribute(SUSPENDED_ATT, true);
+          req.setAttribute(RESUMED_ATT, false);
+          break;
+        case CANCELED:
+          req.setAttribute(CANCELED_ATT, true);
+          break;
+        case RESUMED:
+          req.setAttribute(RESUMED_ATT, true);
+          break;
+        case INITIAL:
+        case UNEXPECTED:
+        default:
+          break;
+      }
+    }
+
+    private static RequestState get(ServletRequest req) {
+      if (Boolean.FALSE.equals(req.getAttribute(RESUMED_ATT))
+          && Boolean.TRUE.equals(req.getAttribute(SUSPENDED_ATT))) {
+        return SUSPENDED;
+      }
+
+      if (req.getDispatcherType() != DispatcherType.ASYNC) {
+        return INITIAL;
+      }
+
+      if (Boolean.TRUE.equals(req.getAttribute(RESUMED_ATT))
+          && Boolean.TRUE.equals(req.getAttribute(CANCELED_ATT))) {
+        return CANCELED;
+      }
+
+      if (Boolean.TRUE.equals(req.getAttribute(RESUMED_ATT))) {
+        return RESUMED;
+      }
+
+      return UNEXPECTED;
+    }
+  }
+
   private final AccountLimits.Factory limitsFactory;
   private final Provider<CurrentUser> user;
   private final QueueProvider queue;
@@ -104,40 +156,50 @@
       throws IOException, ServletException {
     final HttpServletRequest req = (HttpServletRequest) request;
     final HttpServletResponse rsp = (HttpServletResponse) response;
-    final Continuation cont = ContinuationSupport.getContinuation(req);
 
-    if (cont.isInitial()) {
-      TaskThunk task = new TaskThunk(cont, req);
-      if (maxWait > 0) {
-        cont.setTimeout(maxWait);
-      }
-      cont.suspend(rsp);
-      cont.setAttribute(TASK, task);
+    final TaskThunk task;
 
-      Future<?> f = getExecutor().submit(task);
-      cont.addContinuationListener(new Listener(f));
-    } else if (cont.isExpired()) {
-      rsp.sendError(SC_SERVICE_UNAVAILABLE);
+    switch (RequestState.get(request)) {
+      case INITIAL:
+        AsyncContext asyncContext = suspend(request);
+        task = new TaskThunk(asyncContext, req);
+        if (maxWait > 0) {
+          asyncContext.setTimeout(maxWait);
+        }
 
-    } else if (cont.isResumed() && cont.getAttribute(CANCEL) == Boolean.TRUE) {
-      rsp.sendError(SC_SERVICE_UNAVAILABLE);
+        request.setAttribute(TASK, task);
 
-    } else if (cont.isResumed()) {
-      TaskThunk task = (TaskThunk) cont.getAttribute(TASK);
-      try {
-        task.begin(Thread.currentThread());
-        chain.doFilter(req, rsp);
-      } finally {
-        task.end();
-        Thread.interrupted();
-      }
-
-    } else {
-      context.log("Unexpected QoS continuation state, aborting request");
-      rsp.sendError(SC_SERVICE_UNAVAILABLE);
+        Future<?> f = getExecutor().submit(task);
+        asyncContext.addListener(new Listener(f));
+        break;
+      case CANCELED:
+        rsp.sendError(SC_SERVICE_UNAVAILABLE);
+        break;
+      case RESUMED:
+        task = (TaskThunk) request.getAttribute(TASK);
+        try {
+          task.begin(Thread.currentThread());
+          chain.doFilter(req, rsp);
+        } finally {
+          task.end();
+          Thread.interrupted();
+        }
+        break;
+      case SUSPENDED:
+      case UNEXPECTED:
+      default:
+        context.log("Unexpected QoS state, aborting request");
+        rsp.sendError(SC_SERVICE_UNAVAILABLE);
+        break;
     }
   }
 
+  private AsyncContext suspend(ServletRequest request) {
+    AsyncContext asyncContext = request.startAsync();
+    RequestState.SUSPENDED.set(request);
+    return asyncContext;
+  }
+
   private ScheduledThreadPoolExecutor getExecutor() {
     QueueProvider.QueueType qt = limitsFactory.create(user.get()).getQueueType();
     return queue.getQueue(qt);
@@ -149,7 +211,7 @@
   @Override
   public void destroy() {}
 
-  private static final class Listener implements ContinuationListener {
+  private static final class Listener implements AsyncListener {
     final Future<?> future;
 
     Listener(Future<?> future) {
@@ -157,29 +219,35 @@
     }
 
     @Override
-    public void onComplete(Continuation self) {}
+    public void onComplete(AsyncEvent event) throws IOException {}
 
     @Override
-    public void onTimeout(Continuation self) {
+    public void onTimeout(AsyncEvent event) throws IOException {
       future.cancel(true);
     }
+
+    @Override
+    public void onError(AsyncEvent event) throws IOException {}
+
+    @Override
+    public void onStartAsync(AsyncEvent event) throws IOException {}
   }
 
   private final class TaskThunk implements CancelableRunnable {
-    private final Continuation cont;
+    private final AsyncContext asyncContext;
     private final String name;
     private final Object lock = new Object();
     private boolean done;
     private Thread worker;
 
-    TaskThunk(Continuation cont, HttpServletRequest req) {
-      this.cont = cont;
+    TaskThunk(AsyncContext asyncContext, HttpServletRequest req) {
+      this.asyncContext = asyncContext;
       this.name = generateName(req);
     }
 
     @Override
     public void run() {
-      cont.resume();
+      resume();
 
       synchronized (lock) {
         while (!done) {
@@ -212,8 +280,16 @@
 
     @Override
     public void cancel() {
-      cont.setAttribute(CANCEL, Boolean.TRUE);
-      cont.resume();
+      RequestState.CANCELED.set(asyncContext.getRequest());
+      resume();
+    }
+
+    private void resume() {
+      ServletRequest req = asyncContext.getRequest();
+      if (RequestState.SUSPENDED.equals(RequestState.get(req))) {
+        RequestState.RESUMED.set(req);
+        asyncContext.dispatch();
+      }
     }
 
     @Override
diff --git a/java/com/google/gerrit/server/api/changes/FileApiImpl.java b/java/com/google/gerrit/server/api/changes/FileApiImpl.java
index 24902d6..c506b2e 100644
--- a/java/com/google/gerrit/server/api/changes/FileApiImpl.java
+++ b/java/com/google/gerrit/server/api/changes/FileApiImpl.java
@@ -17,16 +17,20 @@
 import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
 
 import com.google.gerrit.extensions.api.changes.FileApi;
+import com.google.gerrit.extensions.common.BlameInfo;
 import com.google.gerrit.extensions.common.DiffInfo;
 import com.google.gerrit.extensions.common.Input;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.change.FileResource;
+import com.google.gerrit.server.restapi.change.GetBlame;
 import com.google.gerrit.server.restapi.change.GetContent;
 import com.google.gerrit.server.restapi.change.GetDiff;
 import com.google.gerrit.server.restapi.change.Reviewed;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
+import java.util.List;
 
 class FileApiImpl implements FileApi {
   interface Factory {
@@ -34,6 +38,7 @@
   }
 
   private final GetContent getContent;
+  private final Provider<GetBlame> getBlame;
   private final GetDiff getDiff;
   private final Reviewed.PutReviewed putReviewed;
   private final Reviewed.DeleteReviewed deleteReviewed;
@@ -42,11 +47,13 @@
   @Inject
   FileApiImpl(
       GetContent getContent,
+      Provider<GetBlame> getBlame,
       GetDiff getDiff,
       Reviewed.PutReviewed putReviewed,
       Reviewed.DeleteReviewed deleteReviewed,
       @Assisted FileResource file) {
     this.getContent = getContent;
+    this.getBlame = getBlame;
     this.getDiff = getDiff;
     this.putReviewed = putReviewed;
     this.deleteReviewed = deleteReviewed;
@@ -132,4 +139,18 @@
       throw asRestApiException("Cannot retrieve diff", e);
     }
   }
+
+  @Override
+  public BlameRequest blameRequest() throws RestApiException {
+    return new BlameRequest() {
+      @Override
+      public List<BlameInfo> get() throws RestApiException {
+        try {
+          return getBlame.get().setBase(isForBase()).apply(file).value();
+        } catch (Exception e) {
+          throw asRestApiException("Cannot retrieve blame", e);
+        }
+      }
+    };
+  }
 }
diff --git a/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java b/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
index d7ab91b..6d7fc15 100644
--- a/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
+++ b/java/com/google/gerrit/server/api/projects/ProjectApiImpl.java
@@ -43,6 +43,7 @@
 import com.google.gerrit.extensions.api.projects.ProjectInput;
 import com.google.gerrit.extensions.api.projects.TagApi;
 import com.google.gerrit.extensions.api.projects.TagInfo;
+import com.google.gerrit.extensions.common.BatchLabelInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.Input;
 import com.google.gerrit.extensions.common.LabelDefinitionInfo;
@@ -77,6 +78,7 @@
 import com.google.gerrit.server.restapi.project.ListDashboards;
 import com.google.gerrit.server.restapi.project.ListLabels;
 import com.google.gerrit.server.restapi.project.ListTags;
+import com.google.gerrit.server.restapi.project.PostLabels;
 import com.google.gerrit.server.restapi.project.ProjectsCollection;
 import com.google.gerrit.server.restapi.project.PutConfig;
 import com.google.gerrit.server.restapi.project.PutDescription;
@@ -131,6 +133,7 @@
   private final Index index;
   private final IndexChanges indexChanges;
   private final Provider<ListLabels> listLabels;
+  private final PostLabels postLabels;
   private final LabelApiImpl.Factory labelApi;
 
   @AssistedInject
@@ -168,6 +171,7 @@
       Index index,
       IndexChanges indexChanges,
       Provider<ListLabels> listLabels,
+      PostLabels postLabels,
       LabelApiImpl.Factory labelApi,
       @Assisted ProjectResource project) {
     this(
@@ -205,6 +209,7 @@
         index,
         indexChanges,
         listLabels,
+        postLabels,
         labelApi,
         null);
   }
@@ -244,6 +249,7 @@
       Index index,
       IndexChanges indexChanges,
       Provider<ListLabels> listLabels,
+      PostLabels postLabels,
       LabelApiImpl.Factory labelApi,
       @Assisted String name) {
     this(
@@ -281,6 +287,7 @@
         index,
         indexChanges,
         listLabels,
+        postLabels,
         labelApi,
         name);
   }
@@ -320,6 +327,7 @@
       Index index,
       IndexChanges indexChanges,
       Provider<ListLabels> listLabels,
+      PostLabels postLabels,
       LabelApiImpl.Factory labelApi,
       String name) {
     this.permissionBackend = permissionBackend;
@@ -357,6 +365,7 @@
     this.index = index;
     this.indexChanges = indexChanges;
     this.listLabels = listLabels;
+    this.postLabels = postLabels;
     this.labelApi = labelApi;
   }
 
@@ -712,4 +721,13 @@
       throw asRestApiException("Cannot parse label", e);
     }
   }
+
+  @Override
+  public void labels(BatchLabelInput input) throws RestApiException {
+    try {
+      postLabels.apply(checkExists(), input);
+    } catch (Exception e) {
+      throw asRestApiException("Cannot update labels", e);
+    }
+  }
 }
diff --git a/java/com/google/gerrit/server/cache/CacheBackend.java b/java/com/google/gerrit/server/cache/CacheBackend.java
new file mode 100644
index 0000000..ec9876f
--- /dev/null
+++ b/java/com/google/gerrit/server/cache/CacheBackend.java
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.cache;
+
+/** Caffeine is used as default cache backend, but can be overridden with Guava backend. */
+public enum CacheBackend {
+  CAFFEINE,
+  GUAVA;
+
+  public boolean isLegacyBackend() {
+    return this == GUAVA;
+  }
+}
diff --git a/java/com/google/gerrit/server/cache/CacheModule.java b/java/com/google/gerrit/server/cache/CacheModule.java
index 2878624..0fdc6f5 100644
--- a/java/com/google/gerrit/server/cache/CacheModule.java
+++ b/java/com/google/gerrit/server/cache/CacheModule.java
@@ -68,7 +68,8 @@
    */
   protected <K, V> CacheBinding<K, V> cache(
       String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
-    CacheProvider<K, V> m = new CacheProvider<>(this, name, keyType, valType);
+    CacheProvider<K, V> m =
+        new CacheProvider<>(this, name, keyType, valType, CacheBackend.CAFFEINE);
     bindCache(m, name, keyType, valType);
     return m;
   }
@@ -123,7 +124,20 @@
    */
   protected <K, V> PersistentCacheBinding<K, V> persist(
       String name, Class<K> keyType, Class<V> valType) {
-    return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType));
+    return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType), CacheBackend.CAFFEINE);
+  }
+
+  /**
+   * Declare a named in-memory/on-disk cache.
+   *
+   * @param <K> type of key used to lookup entries.
+   * @param <V> type of value stored by the cache.
+   * @param backend cache backend.
+   * @return binding to describe the cache.
+   */
+  protected <K, V> PersistentCacheBinding<K, V> persist(
+      String name, Class<K> keyType, Class<V> valType, CacheBackend backend) {
+    return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType), backend);
   }
 
   /**
@@ -135,7 +149,7 @@
    */
   protected <K, V> PersistentCacheBinding<K, V> persist(
       String name, Class<K> keyType, TypeLiteral<V> valType) {
-    return persist(name, TypeLiteral.get(keyType), valType);
+    return persist(name, TypeLiteral.get(keyType), valType, CacheBackend.CAFFEINE);
   }
 
   /**
@@ -146,8 +160,9 @@
    * @return binding to describe the cache.
    */
   protected <K, V> PersistentCacheBinding<K, V> persist(
-      String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
-    PersistentCacheProvider<K, V> m = new PersistentCacheProvider<>(this, name, keyType, valType);
+      String name, TypeLiteral<K> keyType, TypeLiteral<V> valType, CacheBackend backend) {
+    PersistentCacheProvider<K, V> m =
+        new PersistentCacheProvider<>(this, name, keyType, valType, backend);
     bindCache(m, name, keyType, valType);
 
     Type cacheDefType =
diff --git a/java/com/google/gerrit/server/cache/CacheProvider.java b/java/com/google/gerrit/server/cache/CacheProvider.java
index b1a9b91..fe4244c 100644
--- a/java/com/google/gerrit/server/cache/CacheProvider.java
+++ b/java/com/google/gerrit/server/cache/CacheProvider.java
@@ -30,6 +30,7 @@
 
 class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> {
   private final CacheModule module;
+  private final CacheBackend backend;
   final String name;
   private final TypeLiteral<K> keyType;
   private final TypeLiteral<V> valType;
@@ -44,11 +45,17 @@
   private MemoryCacheFactory memoryCacheFactory;
   private boolean frozen;
 
-  CacheProvider(CacheModule module, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
+  CacheProvider(
+      CacheModule module,
+      String name,
+      TypeLiteral<K> keyType,
+      TypeLiteral<V> valType,
+      CacheBackend backend) {
     this.module = module;
     this.name = name;
     this.keyType = keyType;
     this.valType = valType;
+    this.backend = backend;
   }
 
   @Inject(optional = true)
@@ -159,7 +166,9 @@
   public Cache<K, V> get() {
     freeze();
     CacheLoader<K, V> ldr = loader();
-    return ldr != null ? memoryCacheFactory.build(this, ldr) : memoryCacheFactory.build(this);
+    return ldr != null
+        ? memoryCacheFactory.build(this, ldr, backend)
+        : memoryCacheFactory.build(this, backend);
   }
 
   protected void checkNotFrozen() {
diff --git a/java/com/google/gerrit/server/cache/MemoryCacheFactory.java b/java/com/google/gerrit/server/cache/MemoryCacheFactory.java
index fc55753..558380d 100644
--- a/java/com/google/gerrit/server/cache/MemoryCacheFactory.java
+++ b/java/com/google/gerrit/server/cache/MemoryCacheFactory.java
@@ -19,7 +19,8 @@
 import com.google.common.cache.LoadingCache;
 
 public interface MemoryCacheFactory {
-  <K, V> Cache<K, V> build(CacheDef<K, V> def);
+  <K, V> Cache<K, V> build(CacheDef<K, V> def, CacheBackend backend);
 
-  <K, V> LoadingCache<K, V> build(CacheDef<K, V> def, CacheLoader<K, V> loader);
+  <K, V> LoadingCache<K, V> build(
+      CacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend);
 }
diff --git a/java/com/google/gerrit/server/cache/PersistentCacheFactory.java b/java/com/google/gerrit/server/cache/PersistentCacheFactory.java
index 27fa9ca..93f91ef 100644
--- a/java/com/google/gerrit/server/cache/PersistentCacheFactory.java
+++ b/java/com/google/gerrit/server/cache/PersistentCacheFactory.java
@@ -19,9 +19,10 @@
 import com.google.common.cache.LoadingCache;
 
 public interface PersistentCacheFactory {
-  <K, V> Cache<K, V> build(PersistentCacheDef<K, V> def);
+  <K, V> Cache<K, V> build(PersistentCacheDef<K, V> def, CacheBackend backend);
 
-  <K, V> LoadingCache<K, V> build(PersistentCacheDef<K, V> def, CacheLoader<K, V> loader);
+  <K, V> LoadingCache<K, V> build(
+      PersistentCacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend);
 
   void onStop(String plugin);
 }
diff --git a/java/com/google/gerrit/server/cache/PersistentCacheProvider.java b/java/com/google/gerrit/server/cache/PersistentCacheProvider.java
index 59d66e3..4fc107f 100644
--- a/java/com/google/gerrit/server/cache/PersistentCacheProvider.java
+++ b/java/com/google/gerrit/server/cache/PersistentCacheProvider.java
@@ -30,6 +30,7 @@
 
 class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
     implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> {
+  private final CacheBackend backend;
   private int version;
   private long diskLimit;
   private CacheSerializer<K> keySerializer;
@@ -39,9 +40,19 @@
 
   PersistentCacheProvider(
       CacheModule module, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
-    super(module, name, keyType, valType);
+    this(module, name, keyType, valType, CacheBackend.CAFFEINE);
+  }
+
+  PersistentCacheProvider(
+      CacheModule module,
+      String name,
+      TypeLiteral<K> keyType,
+      TypeLiteral<V> valType,
+      CacheBackend backend) {
+    super(module, name, keyType, valType, backend);
     version = -1;
     diskLimit = 128 << 20;
+    this.backend = backend;
   }
 
   @Inject(optional = true)
@@ -130,8 +141,8 @@
     freeze();
     CacheLoader<K, V> ldr = loader();
     return ldr != null
-        ? persistentCacheFactory.build(this, ldr)
-        : persistentCacheFactory.build(this);
+        ? persistentCacheFactory.build(this, ldr, backend)
+        : persistentCacheFactory.build(this, backend);
   }
 
   private static <T> void checkSerializer(
diff --git a/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java b/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
index af1228d..2b068aa 100644
--- a/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
+++ b/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
@@ -21,6 +21,7 @@
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.server.cache.CacheBackend;
 import com.google.gerrit.server.cache.MemoryCacheFactory;
 import com.google.gerrit.server.cache.PersistentCacheDef;
 import com.google.gerrit.server.cache.PersistentCacheFactory;
@@ -156,18 +157,21 @@
 
   @SuppressWarnings({"unchecked"})
   @Override
-  public <K, V> Cache<K, V> build(PersistentCacheDef<K, V> in) {
+  public <K, V> Cache<K, V> build(PersistentCacheDef<K, V> in, CacheBackend backend) {
     long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit());
 
     if (cacheDir == null || limit <= 0) {
-      return memCacheFactory.build(in);
+      return memCacheFactory.build(in, backend);
     }
 
     H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in);
     SqlStore<K, V> store = newSqlStore(def, limit);
     H2CacheImpl<K, V> cache =
         new H2CacheImpl<>(
-            executor, store, def.keyType(), (Cache<K, ValueHolder<V>>) memCacheFactory.build(def));
+            executor,
+            store,
+            def.keyType(),
+            (Cache<K, ValueHolder<V>>) memCacheFactory.build(def, backend));
     synchronized (caches) {
       caches.add(cache);
     }
@@ -176,11 +180,12 @@
 
   @SuppressWarnings("unchecked")
   @Override
-  public <K, V> LoadingCache<K, V> build(PersistentCacheDef<K, V> in, CacheLoader<K, V> loader) {
+  public <K, V> LoadingCache<K, V> build(
+      PersistentCacheDef<K, V> in, CacheLoader<K, V> loader, CacheBackend backend) {
     long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit());
 
     if (cacheDir == null || limit <= 0) {
-      return memCacheFactory.build(in, loader);
+      return memCacheFactory.build(in, loader, backend);
     }
 
     H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in);
@@ -188,7 +193,9 @@
     Cache<K, ValueHolder<V>> mem =
         (Cache<K, ValueHolder<V>>)
             memCacheFactory.build(
-                def, (CacheLoader<K, V>) new H2CacheImpl.Loader<>(executor, store, loader));
+                def,
+                (CacheLoader<K, V>) new H2CacheImpl.Loader<>(executor, store, loader),
+                backend);
     H2CacheImpl<K, V> cache = new H2CacheImpl<>(executor, store, def.keyType(), mem);
     synchronized (caches) {
       caches.add(cache);
diff --git a/java/com/google/gerrit/server/cache/mem/BUILD b/java/com/google/gerrit/server/cache/mem/BUILD
index d805e1f..a666df7 100644
--- a/java/com/google/gerrit/server/cache/mem/BUILD
+++ b/java/com/google/gerrit/server/cache/mem/BUILD
@@ -8,6 +8,8 @@
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/server",
+        "//lib:caffeine",
+        "//lib:caffeine-guava",
         "//lib:guava",
         "//lib:jgit",
         "//lib/guice",
diff --git a/java/com/google/gerrit/server/cache/mem/DefaultMemoryCacheFactory.java b/java/com/google/gerrit/server/cache/mem/DefaultMemoryCacheFactory.java
index f76b8db..9906b3d 100644
--- a/java/com/google/gerrit/server/cache/mem/DefaultMemoryCacheFactory.java
+++ b/java/com/google/gerrit/server/cache/mem/DefaultMemoryCacheFactory.java
@@ -17,13 +17,18 @@
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.RemovalListener;
+import com.github.benmanes.caffeine.cache.Weigher;
+import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
 import com.google.common.base.Strings;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
-import com.google.common.cache.Weigher;
+import com.google.common.cache.RemovalNotification;
 import com.google.gerrit.common.Nullable;
+import com.google.gerrit.server.cache.CacheBackend;
 import com.google.gerrit.server.cache.CacheDef;
 import com.google.gerrit.server.cache.ForwardingRemovalListener;
 import com.google.gerrit.server.cache.MemoryCacheFactory;
@@ -46,25 +51,30 @@
   }
 
   @Override
-  public <K, V> Cache<K, V> build(CacheDef<K, V> def) {
-    return create(def).build();
+  public <K, V> Cache<K, V> build(CacheDef<K, V> def, CacheBackend backend) {
+    return backend.isLegacyBackend()
+        ? createLegacy(def).build()
+        : CaffeinatedGuava.build(create(def));
   }
 
   @Override
-  public <K, V> LoadingCache<K, V> build(CacheDef<K, V> def, CacheLoader<K, V> loader) {
-    return create(def).build(loader);
+  public <K, V> LoadingCache<K, V> build(
+      CacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend) {
+    return backend.isLegacyBackend()
+        ? createLegacy(def).build(loader)
+        : CaffeinatedGuava.build(create(def), loader);
   }
 
   @SuppressWarnings("unchecked")
-  private <K, V> CacheBuilder<K, V> create(CacheDef<K, V> def) {
-    CacheBuilder<K, V> builder = newCacheBuilder();
+  private <K, V> CacheBuilder<K, V> createLegacy(CacheDef<K, V> def) {
+    CacheBuilder<K, V> builder = newLegacyCacheBuilder();
     builder.recordStats();
     builder.maximumWeight(
         cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight()));
 
     builder = builder.removalListener(forwardingRemovalListenerFactory.create(def.name()));
 
-    Weigher<K, V> weigher = def.weigher();
+    com.google.common.cache.Weigher<K, V> weigher = def.weigher();
     if (weigher == null) {
       weigher = unitWeight();
     }
@@ -98,6 +108,42 @@
     return builder;
   }
 
+  private <K, V> Caffeine<K, V> create(CacheDef<K, V> def) {
+    Caffeine<K, V> builder = newCacheBuilder();
+    builder.recordStats();
+    builder.maximumWeight(
+        cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight()));
+    builder = builder.removalListener(newRemovalListener(def.name()));
+    builder.weigher(newWeigher(def.weigher()));
+
+    Duration expireAfterWrite = def.expireAfterWrite();
+    if (has(def.configKey(), "maxAge")) {
+      builder.expireAfterWrite(
+          ConfigUtil.getTimeUnit(
+              cfg, "cache", def.configKey(), "maxAge", toSeconds(expireAfterWrite), SECONDS),
+          SECONDS);
+    } else if (expireAfterWrite != null) {
+      builder.expireAfterWrite(expireAfterWrite.toNanos(), NANOSECONDS);
+    }
+
+    Duration expireAfterAccess = def.expireFromMemoryAfterAccess();
+    if (has(def.configKey(), "expireFromMemoryAfterAccess")) {
+      builder.expireAfterAccess(
+          ConfigUtil.getTimeUnit(
+              cfg,
+              "cache",
+              def.configKey(),
+              "expireFromMemoryAfterAccess",
+              toSeconds(expireAfterAccess),
+              SECONDS),
+          SECONDS);
+    } else if (expireAfterAccess != null) {
+      builder.expireAfterAccess(expireAfterAccess.toNanos(), NANOSECONDS);
+    }
+
+    return builder;
+  }
+
   private static long toSeconds(@Nullable Duration duration) {
     return duration != null ? duration.getSeconds() : 0;
   }
@@ -107,11 +153,31 @@
   }
 
   @SuppressWarnings("unchecked")
-  private static <K, V> CacheBuilder<K, V> newCacheBuilder() {
+  private static <K, V> CacheBuilder<K, V> newLegacyCacheBuilder() {
     return (CacheBuilder<K, V>) CacheBuilder.newBuilder();
   }
 
-  private static <K, V> Weigher<K, V> unitWeight() {
+  private static <K, V> com.google.common.cache.Weigher<K, V> unitWeight() {
     return (key, value) -> 1;
   }
+
+  @SuppressWarnings("unchecked")
+  private static <K, V> Caffeine<K, V> newCacheBuilder() {
+    return (Caffeine<K, V>) Caffeine.newBuilder();
+  }
+
+  @SuppressWarnings("unchecked")
+  private <V, K> RemovalListener<K, V> newRemovalListener(String cacheName) {
+    return (k, v, cause) ->
+        forwardingRemovalListenerFactory
+            .create(cacheName)
+            .onRemoval(
+                RemovalNotification.create(
+                    k, v, com.google.common.cache.RemovalCause.valueOf(cause.name())));
+  }
+
+  private static <K, V> Weigher<K, V> newWeigher(
+      com.google.common.cache.Weigher<K, V> guavaWeigher) {
+    return guavaWeigher == null ? Weigher.singletonWeigher() : (k, v) -> guavaWeigher.weigh(k, v);
+  }
 }
diff --git a/java/com/google/gerrit/server/change/ActionJson.java b/java/com/google/gerrit/server/change/ActionJson.java
index d493b31..031c1f2 100644
--- a/java/com/google/gerrit/server/change/ActionJson.java
+++ b/java/com/google/gerrit/server/change/ActionJson.java
@@ -136,6 +136,7 @@
     copy._number = changeInfo._number;
     copy.requirements = changeInfo.requirements;
     copy.revertOf = changeInfo.revertOf;
+    copy.submissionId = changeInfo.submissionId;
     copy.starred = changeInfo.starred;
     copy.stars = changeInfo.stars;
     copy.submitted = changeInfo.submitted;
diff --git a/java/com/google/gerrit/server/change/ChangeInserter.java b/java/com/google/gerrit/server/change/ChangeInserter.java
index 1bf5103..4263373 100644
--- a/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -55,6 +55,7 @@
 import com.google.gerrit.server.git.GroupCollector;
 import com.google.gerrit.server.git.validators.CommitValidationException;
 import com.google.gerrit.server.git.validators.CommitValidators;
+import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.mail.send.CreateChangeSender;
 import com.google.gerrit.server.notedb.ChangeUpdate;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
@@ -386,7 +387,7 @@
         psUtil.insert(
             ctx.getRevWalk(), update, psId, commitId, newGroups, pushCert, patchSetDescription);
 
-    /* TODO: fixStatus is used here because the tests
+    /* TODO: fixStatusToMerged is used here because the tests
      * (byStatusClosed() in AbstractQueryChangesTest)
      * insert changes that are already merged,
      * and setStatus may not be used to set the Status to merged
@@ -394,7 +395,11 @@
      * is it possible to make the tests use the merge code path,
      * instead of setting the status directly?
      */
-    update.fixStatus(change.getStatus());
+    if (change.getStatus() == Change.Status.MERGED) {
+      update.fixStatusToMerged(new RequestId(ctx.getChange().getId().toString()));
+    } else {
+      update.setStatus(change.getStatus());
+    }
 
     reviewerAdditions =
         reviewerAdder.prepare(ctx.getNotes(), ctx.getUser(), getReviewerInputs(), true);
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 3b7a2c4..21ee28a 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -138,6 +138,7 @@
           COMMIT_FOOTERS,
           CURRENT_ACTIONS,
           CURRENT_COMMIT,
+          DETAILED_LABELS, // may need to load ChangeNotes to check remove reviewer permissions
           MESSAGES);
 
   @Singleton
@@ -586,6 +587,7 @@
       out.plugins = pluginDefinedAttributesFactory.get().create(cd);
     }
     out.revertOf = cd.change().getRevertOf() != null ? cd.change().getRevertOf().get() : null;
+    out.submissionId = cd.change().getSubmissionId();
 
     if (has(REVIEWER_UPDATES)) {
       out.reviewerUpdates = reviewerUpdates(cd);
diff --git a/java/com/google/gerrit/server/change/ConsistencyChecker.java b/java/com/google/gerrit/server/change/ConsistencyChecker.java
index 0374a1c..19db5ee 100644
--- a/java/com/google/gerrit/server/change/ConsistencyChecker.java
+++ b/java/com/google/gerrit/server/change/ConsistencyChecker.java
@@ -44,6 +44,7 @@
 import com.google.gerrit.server.PatchSetUtil;
 import com.google.gerrit.server.account.Accounts;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.notedb.PatchSetState;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
@@ -576,7 +577,8 @@
     @Override
     public boolean updateChange(ChangeContext ctx) {
       ctx.getChange().setStatus(Change.Status.MERGED);
-      ctx.getUpdate(ctx.getChange().currentPatchSetId()).fixStatus(Change.Status.MERGED);
+      ctx.getUpdate(ctx.getChange().currentPatchSetId())
+          .fixStatusToMerged(new RequestId(ctx.getChange().getId().toString()));
       p.status = Status.FIXED;
       p.outcome = "Marked change as merged";
       return true;
diff --git a/java/com/google/gerrit/server/git/HookUtil.java b/java/com/google/gerrit/server/git/HookUtil.java
index 3bef7cc..e160e71 100644
--- a/java/com/google/gerrit/server/git/HookUtil.java
+++ b/java/com/google/gerrit/server/git/HookUtil.java
@@ -19,7 +19,7 @@
 import java.io.IOException;
 import java.util.Map;
 import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.transport.BaseReceivePack;
+import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
 
 /** Static utilities for writing git protocol hooks. */
@@ -32,8 +32,7 @@
    * @return map of refs that were advertised.
    * @throws ServiceMayNotContinueException if a problem occurred.
    */
-  @SuppressWarnings("deprecation")
-  public static Map<String, Ref> ensureAllRefsAdvertised(BaseReceivePack rp)
+  public static Map<String, Ref> ensureAllRefsAdvertised(ReceivePack rp)
       throws ServiceMayNotContinueException {
     Map<String, Ref> refs = rp.getAdvertisedRefs();
     if (refs != null) {
diff --git a/java/com/google/gerrit/server/git/MergedByPushOp.java b/java/com/google/gerrit/server/git/MergedByPushOp.java
index 858a55a..c8b5e3f 100644
--- a/java/com/google/gerrit/server/git/MergedByPushOp.java
+++ b/java/com/google/gerrit/server/git/MergedByPushOp.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.server.PatchSetUtil;
 import com.google.gerrit.server.config.SendEmailExecutor;
 import com.google.gerrit.server.extensions.events.ChangeMerged;
+import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.mail.send.MergedSender;
 import com.google.gerrit.server.notedb.ChangeUpdate;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
@@ -132,9 +133,11 @@
     }
     change.setCurrentPatchSet(info);
     change.setStatus(Change.Status.MERGED);
+    RequestId submissionId = new RequestId(change.getId().toString());
+    change.setSubmissionId(submissionId.toStringForStorage());
     // we cannot reconstruct the submit records for when this change was
-    // submitted, this is why we must fix the status
-    update.fixStatus(Change.Status.MERGED);
+    // submitted, this is why we must fix the status and other details.
+    update.fixStatusToMerged(submissionId);
     update.setCurrentPatchSet();
     if (change.isWorkInProgress()) {
       change.setWorkInProgress(false);
diff --git a/java/com/google/gerrit/server/git/WorkQueue.java b/java/com/google/gerrit/server/git/WorkQueue.java
index 0361117..f2a0ff1 100644
--- a/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/java/com/google/gerrit/server/git/WorkQueue.java
@@ -95,7 +95,7 @@
 
   @Inject
   WorkQueue(IdGenerator idGenerator, @GerritServerConfig Config cfg, MetricMaker metrics) {
-    this(idGenerator, cfg.getInt("execution", "defaultThreadPoolSize", 1), metrics);
+    this(idGenerator, Math.max(cfg.getInt("execution", "defaultThreadPoolSize", 2), 2), metrics);
   }
 
   /** Constructor to allow binding the WorkQueue more explicitly in a vhost setup. */
diff --git a/java/com/google/gerrit/server/git/receive/AllRefsWatcher.java b/java/com/google/gerrit/server/git/receive/AllRefsWatcher.java
index c092c43..13ae54a 100644
--- a/java/com/google/gerrit/server/git/receive/AllRefsWatcher.java
+++ b/java/com/google/gerrit/server/git/receive/AllRefsWatcher.java
@@ -20,7 +20,7 @@
 import java.util.Map;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.transport.AdvertiseRefsHook;
-import org.eclipse.jgit.transport.BaseReceivePack;
+import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
 import org.eclipse.jgit.transport.UploadPack;
 
@@ -34,7 +34,7 @@
   private Map<String, Ref> allRefs;
 
   @Override
-  public void advertiseRefs(BaseReceivePack rp) throws ServiceMayNotContinueException {
+  public void advertiseRefs(ReceivePack rp) throws ServiceMayNotContinueException {
     allRefs = HookUtil.ensureAllRefsAdvertised(rp);
   }
 
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index 7038736..7767fe2 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -310,7 +310,8 @@
 
     allRefsWatcher = new AllRefsWatcher();
     receivePack.setAdvertiseRefsHook(
-        ReceiveCommitsAdvertiseRefsHookChain.create(allRefsWatcher, queryProvider, projectName));
+        ReceiveCommitsAdvertiseRefsHookChain.create(
+            allRefsWatcher, queryProvider, projectName, user.getAccountId()));
     resultChangeIds = new ResultChangeIds();
     receiveCommits =
         factory.create(
diff --git a/java/com/google/gerrit/server/git/receive/BUILD b/java/com/google/gerrit/server/git/receive/BUILD
index 2b04d4d..7402a37 100644
--- a/java/com/google/gerrit/server/git/receive/BUILD
+++ b/java/com/google/gerrit/server/git/receive/BUILD
@@ -15,6 +15,7 @@
         "//java/com/google/gerrit/exceptions",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/git",
+        "//java/com/google/gerrit/index",
         "//java/com/google/gerrit/metrics",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/logging",
diff --git a/java/com/google/gerrit/server/git/receive/HackPushNegotiateHook.java b/java/com/google/gerrit/server/git/receive/HackPushNegotiateHook.java
index 2ee9a64..72483af 100644
--- a/java/com/google/gerrit/server/git/receive/HackPushNegotiateHook.java
+++ b/java/com/google/gerrit/server/git/receive/HackPushNegotiateHook.java
@@ -28,7 +28,7 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.AdvertiseRefsHook;
-import org.eclipse.jgit.transport.BaseReceivePack;
+import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
 import org.eclipse.jgit.transport.UploadPack;
 
@@ -72,9 +72,8 @@
     throw new UnsupportedOperationException("HackPushNegotiateHook cannot be used for UploadPack");
   }
 
-  @SuppressWarnings("deprecation")
   @Override
-  public void advertiseRefs(BaseReceivePack rp) throws ServiceMayNotContinueException {
+  public void advertiseRefs(ReceivePack rp) throws ServiceMayNotContinueException {
     Map<String, Ref> r = rp.getAdvertisedRefs();
     if (r == null) {
       try {
@@ -90,14 +89,13 @@
     rp.setAdvertisedRefs(r, history(r.values(), rp));
   }
 
-  private Set<ObjectId> history(Collection<Ref> refs, BaseReceivePack rp) {
+  private Set<ObjectId> history(Collection<Ref> refs, ReceivePack rp) {
     Set<ObjectId> alreadySending = rp.getAdvertisedObjects();
     if (MAX_HISTORY <= alreadySending.size()) {
       return alreadySending;
     }
 
     // Scan history until the advertisement is full.
-    @SuppressWarnings("deprecation")
     RevWalk rw = rp.getRevWalk();
     rw.reset();
     try {
diff --git a/java/com/google/gerrit/server/git/receive/LazyPostReceiveHookChain.java b/java/com/google/gerrit/server/git/receive/LazyPostReceiveHookChain.java
index 700851c..a19dbac 100644
--- a/java/com/google/gerrit/server/git/receive/LazyPostReceiveHookChain.java
+++ b/java/com/google/gerrit/server/git/receive/LazyPostReceiveHookChain.java
@@ -61,7 +61,7 @@
   @Override
   public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
     hooks.runEach(h -> h.onPostReceive(rp, commands));
-    if (affectsSize(rp, commands)) {
+    if (affectsSize(rp)) {
       QuotaResponse.Aggregated a =
           quotaBackend
               .user(user)
@@ -78,14 +78,7 @@
     }
   }
 
-  public static boolean affectsSize(ReceivePack rp, Collection<ReceiveCommand> commands) {
-    if (rp.getPackSize() > 0L) {
-      for (ReceiveCommand cmd : commands) {
-        if (cmd.getType() != ReceiveCommand.Type.DELETE) {
-          return true;
-        }
-      }
-    }
-    return false;
+  public static boolean affectsSize(ReceivePack rp) {
+    return rp.hasReceivedPack() && rp.getPackSize() > 0L;
   }
 }
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
index 1b22e1f..6c1f097 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHook.java
@@ -18,14 +18,19 @@
 
 import com.google.common.collect.Sets;
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.exceptions.StorageException;
+import com.google.gerrit.index.query.Predicate;
 import com.google.gerrit.server.git.HookUtil;
 import com.google.gerrit.server.index.change.ChangeField;
 import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.ChangeStatusPredicate;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.query.change.OwnerPredicate;
+import com.google.gerrit.server.query.change.ProjectPredicate;
 import com.google.gerrit.server.util.MagicBranch;
 import com.google.inject.Provider;
 import java.io.IOException;
@@ -36,7 +41,7 @@
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.transport.AdvertiseRefsHook;
-import org.eclipse.jgit.transport.BaseReceivePack;
+import org.eclipse.jgit.transport.ReceivePack;
 import org.eclipse.jgit.transport.ServiceMayNotContinueException;
 import org.eclipse.jgit.transport.UploadPack;
 
@@ -65,11 +70,13 @@
 
   private final Provider<InternalChangeQuery> queryProvider;
   private final Project.NameKey projectName;
+  private final Account.Id user;
 
   public ReceiveCommitsAdvertiseRefsHook(
-      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName) {
+      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName, Account.Id user) {
     this.queryProvider = queryProvider;
     this.projectName = projectName;
+    this.user = user;
   }
 
   @Override
@@ -78,9 +85,8 @@
         "ReceiveCommitsAdvertiseRefsHook cannot be used for UploadPack");
   }
 
-  @SuppressWarnings("deprecation")
   @Override
-  public void advertiseRefs(BaseReceivePack rp) throws ServiceMayNotContinueException {
+  public void advertiseRefs(ReceivePack rp) throws ServiceMayNotContinueException {
     Map<String, Ref> advertisedRefs = HookUtil.ensureAllRefsAdvertised(rp);
     advertisedRefs.keySet().stream()
         .filter(ReceiveCommitsAdvertiseRefsHook::skip)
@@ -91,7 +97,9 @@
 
   private Set<ObjectId> advertiseOpenChanges(Repository repo)
       throws ServiceMayNotContinueException {
-    // Advertise some recent open changes, in case a commit is based on one.
+    // Advertise the user's most recent open changes. It's likely that the user has one of these in
+    // their local repo and they can serve as starting points to figure out the common ancestor of
+    // what the client and server have in common.
     int limit = 32;
     try {
       Set<ObjectId> r = Sets.newHashSetWithExpectedSize(limit);
@@ -106,7 +114,11 @@
                   ChangeField.PATCH_SET)
               .enforceVisibility(true)
               .setLimit(limit)
-              .byProjectOpen(projectName)) {
+              .query(
+                  Predicate.and(
+                      new ProjectPredicate(projectName.get()),
+                      ChangeStatusPredicate.open(),
+                      new OwnerPredicate(user)))) {
         PatchSet ps = cd.currentPatchSet();
         if (ps != null) {
           // Ensure we actually observed a patch set ref pointing to this
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
index 76f6b04..fae1401 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommitsAdvertiseRefsHookChain.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.git.receive;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.inject.Provider;
@@ -35,8 +36,9 @@
   public static AdvertiseRefsHook create(
       AllRefsWatcher allRefsWatcher,
       Provider<InternalChangeQuery> queryProvider,
-      Project.NameKey projectName) {
-    return create(allRefsWatcher, queryProvider, projectName, false);
+      Project.NameKey projectName,
+      Account.Id user) {
+    return create(allRefsWatcher, queryProvider, projectName, user, false);
   }
 
   /**
@@ -47,18 +49,19 @@
    */
   @VisibleForTesting
   public static AdvertiseRefsHook createForTest(
-      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName) {
-    return create(new AllRefsWatcher(), queryProvider, projectName, true);
+      Provider<InternalChangeQuery> queryProvider, Project.NameKey projectName, Account.Id user) {
+    return create(new AllRefsWatcher(), queryProvider, projectName, user, true);
   }
 
   private static AdvertiseRefsHook create(
       AllRefsWatcher allRefsWatcher,
       Provider<InternalChangeQuery> queryProvider,
       Project.NameKey projectName,
+      Account.Id user,
       boolean skipHackPushNegotiateHook) {
     List<AdvertiseRefsHook> advHooks = new ArrayList<>();
     advHooks.add(allRefsWatcher);
-    advHooks.add(new ReceiveCommitsAdvertiseRefsHook(queryProvider, projectName));
+    advHooks.add(new ReceiveCommitsAdvertiseRefsHook(queryProvider, projectName, user));
     if (!skipHackPushNegotiateHook) {
       advHooks.add(new HackPushNegotiateHook());
     }
diff --git a/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java b/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
index f6d3b6f..5efa065 100644
--- a/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
+++ b/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
@@ -76,7 +76,7 @@
     this.accountCache = accountCache;
     this.indexer = indexer;
     this.executor = executor;
-    this.enabled = cfg.getBoolean("index", null, "reindexAfterRefUpdate", true);
+    this.enabled = cfg.getBoolean("index", "change", "indexMergeable", true);
   }
 
   @Override
diff --git a/java/com/google/gerrit/server/logging/RequestId.java b/java/com/google/gerrit/server/logging/RequestId.java
index ceb5da0..543f0a2 100644
--- a/java/com/google/gerrit/server/logging/RequestId.java
+++ b/java/com/google/gerrit/server/logging/RequestId.java
@@ -72,6 +72,6 @@
   }
 
   public String toStringForStorage() {
-    return str.substring(1, str.length() - 1);
+    return str;
   }
 }
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index a390de3..7d2fa0a 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -127,11 +127,19 @@
             // this message so they can always review and audit what we sent
             // on their behalf to others.
             //
+            logger.atFine().log(
+                "CC email sender %s because the email strategy of this user is %s",
+                fromUser.get().account().id(), CC_ON_OWN_COMMENTS);
             add(RecipientType.CC, fromId);
           } else if (!notify.accounts().containsValue(fromId) && rcptTo.remove(fromId)) {
             // If they don't want a copy, but we queued one up anyway,
             // drop them from the recipient lists.
             //
+            logger.atFine().log(
+                "Not CCing email sender %s because the email strategy of this user is not %s but %s",
+                fromUser.get().account().id(),
+                CC_ON_OWN_COMMENTS,
+                senderPrefs != null ? senderPrefs.getEmailStrategy() : null);
             removeUser(fromUser.get().account());
           }
         }
@@ -145,8 +153,12 @@
           Account thisUserAccount = thisUser.get().account();
           GeneralPreferencesInfo prefs = thisUser.get().generalPreferences();
           if (prefs == null || prefs.getEmailStrategy() == DISABLED) {
+            logger.atFine().log(
+                "Not emailing account %s because user has set email strategy to %s", id, DISABLED);
             removeUser(thisUserAccount);
           } else if (useHtml() && prefs.getEmailFormat() == EmailFormat.PLAINTEXT) {
+            logger.atFine().log(
+                "Removing account %s from HTML email because user prefers plain text emails", id);
             removeUser(thisUserAccount);
             smtpRcptToPlaintextOnly.add(
                 new Address(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
@@ -206,12 +218,13 @@
 
       if (!smtpRcptTo.isEmpty()) {
         // Send multipart message
-        logger.atFine().log("Sending multipart '%s'", messageClass);
+        logger.atFine().log(
+            "Sending multipart '%s' from %s to %s",
+            messageClass, va.smtpFromAddress, va.smtpRcptTo);
         args.emailSender.send(va.smtpFromAddress, va.smtpRcptTo, va.headers, va.body, va.htmlBody);
       }
 
       if (!smtpRcptToPlaintextOnly.isEmpty()) {
-        logger.atFine().log("Sending plaintext '%s'", messageClass);
         // Send plaintext message
         Map<String, EmailHeader> shallowCopy = new HashMap<>();
         shallowCopy.putAll(headers);
@@ -224,6 +237,9 @@
           to.add(a);
           shallowCopy.put(FieldName.TO, to);
         }
+        logger.atFine().log(
+            "Sending plaintext '%s' from %s to %s",
+            messageClass, va.smtpFromAddress, smtpRcptToPlaintextOnly);
         args.emailSender.send(va.smtpFromAddress, smtpRcptToPlaintextOnly, shallowCopy, va.body);
       }
     }
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index 0acf20e..9a1ba35 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -76,6 +76,7 @@
     }
   }
 
+  /** An {@link AutoCloseable} for parsing a single commit into ChangeNotesCommits. */
   public static class LoadHandle implements AutoCloseable {
     private final Repository repo;
     private final ObjectId id;
diff --git a/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java b/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
index 877022e..7ca0b86 100644
--- a/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeDraftUpdate.java
@@ -20,6 +20,7 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.collect.Sets;
+import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.Comment;
@@ -55,6 +56,8 @@
  * <p>This class is not thread safe.
  */
 public class ChangeDraftUpdate extends AbstractChangeUpdate {
+  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
   public interface Factory {
     ChangeDraftUpdate create(
         ChangeNotes notes,
@@ -203,6 +206,7 @@
       cache.get(k.commitId()).deleteComment(k.key());
     }
 
+    // keyed by commit ID.
     Map<ObjectId, RevisionNoteBuilder> builders = cache.getBuilders();
     boolean touchedAnyRevs = false;
     boolean hasComments = false;
@@ -229,14 +233,14 @@
       return NO_OP_UPDATE;
     }
 
-    // If we touched every revision and there are no comments left, tell the
+    // If there are no comments left, tell the
     // caller to delete the entire ref.
-    boolean touchedAllRevs = updatedCommits.equals(rnm.revisionNotes.keySet());
-    if (touchedAllRevs && !hasComments) {
+    if (!rnm.noteMap.iterator().hasNext()) {
       return null;
     }
 
-    cb.setTreeId(rnm.noteMap.writeTree(ins));
+    ObjectId treeId = rnm.noteMap.writeTree(ins);
+    cb.setTreeId(treeId);
     return cb;
   }
 
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java b/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
index 78f6afc..71cb8c9 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesCommit.java
@@ -43,6 +43,8 @@
  * </ul>
  */
 public class ChangeNotesCommit extends RevCommit {
+
+  /** A {@link RevWalk} producing {@link ChangeNotesCommit}s. */
   public static ChangeNotesRevWalk newRevWalk(Repository repo) {
     return new ChangeNotesRevWalk(repo);
   }
@@ -62,6 +64,7 @@
     };
   }
 
+  /** A {@link RevWalk} that creates {@link ChangeNotesCommit}s rather than {@link RevCommit}s */
   public static class ChangeNotesRevWalk extends RevWalk {
     private ChangeNotesRevWalk(Repository repo) {
       super(repo);
diff --git a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
index b6443f1..4e52093 100644
--- a/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/ChangeRevisionNote.java
@@ -28,6 +28,7 @@
 import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.util.MutableInteger;
 
+/** Implements the parsing of comment data, handling JSON decoding and push certificates. */
 class ChangeRevisionNote extends RevisionNote<Comment> {
   private final ChangeNoteJson noteJson;
   private final Comment.Status status;
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index c0cd173..02a4dcc 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -216,12 +216,14 @@
   }
 
   public void setStatus(Change.Status status) {
-    checkArgument(status != Change.Status.MERGED, "use merge(Iterable<SubmitRecord>)");
+    checkArgument(status != Change.Status.MERGED, "use merge(RequestId, Iterable<SubmitRecord>)");
     this.status = status;
   }
 
-  public void fixStatus(Change.Status status) {
-    this.status = status;
+  public void fixStatusToMerged(RequestId submissionId) {
+    checkArgument(submissionId != null, "submission id must be set for merged changes");
+    this.status = Change.Status.MERGED;
+    this.submissionId = submissionId.toStringForStorage();
   }
 
   public void putApproval(String label, short value) {
diff --git a/java/com/google/gerrit/server/notedb/RevisionNote.java b/java/com/google/gerrit/server/notedb/RevisionNote.java
index ff649a9..cd11e1b 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNote.java
@@ -26,6 +26,10 @@
 import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.util.MutableInteger;
 
+/**
+ * Data stored in a note, parsed on demand. The data type to parse into is a generic list of type T.
+ * The source of the data is a array of raw bytes
+ */
 @UsedAt(UsedAt.Project.PLUGIN_CHECKS)
 public abstract class RevisionNote<T> {
   static final int MAX_NOTE_SZ = 25 << 20;
@@ -64,6 +68,7 @@
     return entities;
   }
 
+  /** Reads the raw data, and delegates parsing to the {@link #parse(byte[], int)} method. */
   public void parse() throws IOException, ConfigInvalidException {
     raw = reader.open(noteId, OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ);
     MutableInteger p = new MutableInteger();
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java b/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
index e63737c..81273dc 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteBuilder.java
@@ -36,6 +36,7 @@
 import org.eclipse.jgit.lib.ObjectId;
 
 class RevisionNoteBuilder {
+  /** Construct a new RevisionNoteMap, seeding it with an existing (immutable) RevisionNoteMap */
   static class Cache {
     private final RevisionNoteMap<? extends RevisionNote<? extends Comment>> revisionNoteMap;
     private final Map<ObjectId, RevisionNoteBuilder> builders;
diff --git a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
index 3e1bad1..cf16073 100644
--- a/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
+++ b/java/com/google/gerrit/server/notedb/RevisionNoteMap.java
@@ -25,8 +25,16 @@
 import org.eclipse.jgit.notes.Note;
 import org.eclipse.jgit.notes.NoteMap;
 
+/**
+ * A utility class that parses a NoteMap into commit => comment list data.
+ *
+ * @param <T> the RevisionNote for the comment type.
+ */
 class RevisionNoteMap<T extends RevisionNote<? extends Comment>> {
+  // CommitID => blob ID
   final NoteMap noteMap;
+
+  // CommitID => parsed data, immutable map.
   final ImmutableMap<ObjectId, T> revisionNotes;
 
   static RevisionNoteMap<ChangeRevisionNote> parse(
@@ -36,6 +44,7 @@
     for (Note note : noteMap) {
       ChangeRevisionNote rn = new ChangeRevisionNote(noteJson, reader, note.getData(), status);
       rn.parse();
+
       result.put(note.copy(), rn);
     }
     return new RevisionNoteMap<>(noteMap, ImmutableMap.copyOf(result));
diff --git a/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java b/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
index 97a8ad4..fc4c9fd 100644
--- a/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
+++ b/java/com/google/gerrit/server/notedb/RobotCommentsRevisionNote.java
@@ -26,6 +26,7 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectReader;
 
+/** Like {@link RevisionNote} but for robot comments. */
 public class RobotCommentsRevisionNote extends RevisionNote<RobotComment> {
   private final ChangeNoteJson noteUtil;
 
diff --git a/java/com/google/gerrit/server/patch/PatchListCacheImpl.java b/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
index 6871652..15fa0f4 100644
--- a/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
+++ b/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
+import com.google.gerrit.server.cache.CacheBackend;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.inject.Inject;
@@ -45,7 +46,9 @@
       @Override
       protected void configure() {
         factory(PatchListLoader.Factory.class);
-        persist(FILE_NAME, PatchListKey.class, PatchList.class)
+        // TODO(davido): Switch off using legacy cache backend, after fixing PatchListLoader
+        // to be recursion free.
+        persist(FILE_NAME, PatchListKey.class, PatchList.class, CacheBackend.GUAVA)
             .maximumWeight(10 << 20)
             .weigher(PatchListWeigher.class);
 
diff --git a/java/com/google/gerrit/server/permissions/RefControl.java b/java/com/google/gerrit/server/permissions/RefControl.java
index 06fe471..378a512 100644
--- a/java/com/google/gerrit/server/permissions/RefControl.java
+++ b/java/com/google/gerrit/server/permissions/RefControl.java
@@ -440,8 +440,7 @@
     @Override
     public ForChange change(ChangeData cd) {
       try {
-        // TODO(hiesel) Force callers to call database() and use db instead of cd.db()
-        return getProjectControl().controlFor(cd.change()).asForChange(cd);
+        return getProjectControl().controlFor(cd.notes()).asForChange(cd);
       } catch (StorageException e) {
         return FailedPermissionBackend.change("unavailable", e);
       }
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index c6beac4..78ca0fc 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -598,7 +598,11 @@
       committer = c.getCommitterIdent();
       parentCount = c.getParentCount();
     } catch (IOException e) {
-      throw new StorageException(e);
+      throw new StorageException(
+          String.format(
+              "Loading commit %s for ps %d of change %d failed.",
+              ps.commitId(), ps.id().get(), ps.id().changeId().get()),
+          e);
     }
     return true;
   }
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 5d4edc9..61b90f1 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -63,6 +63,7 @@
 import com.google.gerrit.server.change.ChangeTriplet;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.OperatorAliasConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.index.change.ChangeField;
@@ -94,6 +95,7 @@
 import java.util.regex.Pattern;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Repository;
 
 /** Parses a query string meant to be applied to change objects. */
@@ -221,6 +223,7 @@
     final GroupMembers groupMembers;
     final Provider<AnonymousUser> anonymousUserProvider;
     final OperatorAliasConfig operatorAliasConfig;
+    final boolean indexMergeable;
 
     private final Provider<CurrentUser> self;
 
@@ -253,7 +256,8 @@
         AccountCache accountCache,
         GroupMembers groupMembers,
         Provider<AnonymousUser> anonymousUserProvider,
-        OperatorAliasConfig operatorAliasConfig) {
+        OperatorAliasConfig operatorAliasConfig,
+        @GerritServerConfig Config gerritConfig) {
       this(
           queryProvider,
           rewriter,
@@ -281,7 +285,8 @@
           accountCache,
           groupMembers,
           anonymousUserProvider,
-          operatorAliasConfig);
+          operatorAliasConfig,
+          gerritConfig.getBoolean("index", "change", "indexMergeable", true));
     }
 
     private Arguments(
@@ -311,7 +316,8 @@
         AccountCache accountCache,
         GroupMembers groupMembers,
         Provider<AnonymousUser> anonymousUserProvider,
-        OperatorAliasConfig operatorAliasConfig) {
+        OperatorAliasConfig operatorAliasConfig,
+        boolean indexMergeable) {
       this.queryProvider = queryProvider;
       this.rewriter = rewriter;
       this.opFactories = opFactories;
@@ -339,6 +345,7 @@
       this.groupMembers = groupMembers;
       this.anonymousUserProvider = anonymousUserProvider;
       this.operatorAliasConfig = operatorAliasConfig;
+      this.indexMergeable = indexMergeable;
     }
 
     Arguments asUser(CurrentUser otherUser) {
@@ -369,7 +376,8 @@
           accountCache,
           groupMembers,
           anonymousUserProvider,
-          operatorAliasConfig);
+          operatorAliasConfig,
+          indexMergeable);
     }
 
     Arguments asUser(Account.Id otherId) {
@@ -570,6 +578,9 @@
     }
 
     if ("mergeable".equalsIgnoreCase(value)) {
+      if (!args.indexMergeable) {
+        throw new QueryParseException("server does not support 'mergeable'. check configs");
+      }
       return new BooleanPredicate(ChangeField.MERGEABLE);
     }
 
@@ -1245,6 +1256,15 @@
     throw new QueryParseException("'revertof' operator is not supported by change index version");
   }
 
+  @Operator
+  public Predicate<ChangeData> submissionId(String value) throws QueryParseException {
+    if (args.getSchema().hasField(ChangeField.SUBMISSIONID)) {
+      return new SubmissionIdPredicate(value);
+    }
+    throw new QueryParseException(
+        "'submissionid' operator is not supported by change index version");
+  }
+
   @Override
   protected Predicate<ChangeData> defaultField(String query) throws QueryParseException {
     if (query.startsWith("refs/")) {
diff --git a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
index a40cdd0..f9e753c 100644
--- a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
+++ b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
@@ -43,6 +43,7 @@
 import com.google.gerrit.server.query.account.AccountQueryBuilder;
 import com.google.gerrit.server.query.account.AccountQueryProcessor;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.LinkedHashMap;
@@ -58,12 +59,13 @@
   private final PermissionBackend permissionBackend;
   private final AccountLoader.Factory accountLoaderFactory;
   private final AccountQueryBuilder queryBuilder;
-  private final AccountQueryProcessor queryProcessor;
+  private final Provider<AccountQueryProcessor> queryProcessorProvider;
   private final boolean suggestConfig;
   private final int suggestFrom;
 
   private AccountLoader accountLoader;
   private boolean suggest;
+  private Integer limit;
   private int suggestLimit = 10;
   private String query;
   private Integer start;
@@ -80,7 +82,7 @@
       metaVar = "CNT",
       usage = "maximum number of users to return")
   public void setLimit(int n) {
-    queryProcessor.setUserProvidedLimit(n);
+    this.limit = n;
 
     if (n < 0) {
       suggestLimit = 10;
@@ -124,12 +126,12 @@
       PermissionBackend permissionBackend,
       AccountLoader.Factory accountLoaderFactory,
       AccountQueryBuilder queryBuilder,
-      AccountQueryProcessor queryProcessor,
+      Provider<AccountQueryProcessor> queryProcessorProvider,
       @GerritServerConfig Config cfg) {
     this.permissionBackend = permissionBackend;
     this.accountLoaderFactory = accountLoaderFactory;
     this.queryBuilder = queryBuilder;
-    this.queryProcessor = queryProcessor;
+    this.queryProcessorProvider = queryProcessorProvider;
     this.suggestFrom = cfg.getInt("suggest", null, "from", 0);
     this.options = EnumSet.noneOf(ListAccountsOption.class);
 
@@ -186,10 +188,15 @@
     }
     accountLoader = accountLoaderFactory.create(fillOptions);
 
+    AccountQueryProcessor queryProcessor = queryProcessorProvider.get();
     if (queryProcessor.isDisabled()) {
       throw new MethodNotAllowedException("query disabled");
     }
 
+    if (limit != null) {
+      queryProcessor.setUserProvidedLimit(limit);
+    }
+
     if (start != null) {
       queryProcessor.setStart(start);
     }
diff --git a/java/com/google/gerrit/server/restapi/change/GetBlame.java b/java/com/google/gerrit/server/restapi/change/GetBlame.java
index e77dba2..12b4d44 100644
--- a/java/com/google/gerrit/server/restapi/change/GetBlame.java
+++ b/java/com/google/gerrit/server/restapi/change/GetBlame.java
@@ -76,6 +76,11 @@
     this.autoMerger = autoMerger;
   }
 
+  public GetBlame setBase(boolean base) {
+    this.base = base;
+    return this;
+  }
+
   @Override
   public Response<List<BlameInfo>> apply(FileResource resource)
       throws RestApiException, IOException, InvalidChangeOperationException {
diff --git a/java/com/google/gerrit/server/restapi/change/GetDiff.java b/java/com/google/gerrit/server/restapi/change/GetDiff.java
index 74562c2..a6536ce 100644
--- a/java/com/google/gerrit/server/restapi/change/GetDiff.java
+++ b/java/com/google/gerrit/server/restapi/change/GetDiff.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.common.data.PatchScript;
 import com.google.gerrit.common.data.PatchScript.DisplayMethod;
 import com.google.gerrit.entities.Patch;
@@ -73,6 +74,8 @@
 import org.kohsuke.args4j.spi.Setter;
 
 public class GetDiff implements RestReadView<FileResource> {
+  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
   private static final ImmutableMap<Patch.ChangeType, ChangeType> CHANGE_TYPE =
       Maps.immutableEnumMap(
           new ImmutableMap.Builder<Patch.ChangeType, ChangeType>()
@@ -134,11 +137,17 @@
     }
     prefs.context = context;
     prefs.intralineDifference = intraline;
+    logger.atFine().log(
+        "diff preferences: ignoreWhitespace = %s, context = %s, intralineDifference = %s",
+        prefs.ignoreWhitespace, prefs.context, prefs.intralineDifference);
 
     PatchScriptFactory psf;
     PatchSet basePatchSet = null;
     PatchSet.Id pId = resource.getPatchKey().patchSetId();
     String fileName = resource.getPatchKey().fileName();
+    logger.atFine().log(
+        "patchSetId = %d, fileName = %s, base = %s, parentNum = %d",
+        pId.get(), fileName, base, parentNum);
     ChangeNotes notes = resource.getRevision().getNotes();
     if (base != null) {
       RevisionResource baseResource =
@@ -158,7 +167,10 @@
       ContentCollector contentCollector = new ContentCollector(ps);
       Set<Edit> editsDueToRebase = ps.getEditsDueToRebase();
       for (Edit edit : ps.getEdits()) {
+        logger.atFine().log("next edit = %s", edit);
+
         if (edit.getType() == Edit.Type.EMPTY) {
+          logger.atFine().log("skip empty edit");
           continue;
         }
         contentCollector.addCommon(edit.getBeginA());
@@ -197,6 +209,7 @@
           resource.getRevision().getEdit().isPresent()
               ? resource.getRevision().getEdit().get().getRefName()
               : resource.getRevision().getPatchSet().refName();
+      logger.atFine().log("revA = %s, revB = %s", revA, revB);
 
       ImmutableList<DiffWebLinkInfo> links =
           webLinks.getDiffLinks(
@@ -243,9 +256,11 @@
         } else {
           result.intralineStatus = IntraLineStatus.OK;
         }
+        logger.atFine().log("intralineStatus = %s", result.intralineStatus);
       }
 
       result.changeType = CHANGE_TYPE.get(ps.getChangeType());
+      logger.atFine().log("changeType = %s", result.changeType);
       if (result.changeType == null) {
         throw new IllegalStateException("unknown change type: " + ps.getChangeType());
       }
@@ -314,18 +329,29 @@
     }
 
     void addCommon(int end) {
+      logger.atFine().log("addCommon: end = %d", end);
+
       end = Math.min(end, fileA.size());
+      logger.atFine().log("end = %d", end);
+
       if (nextA >= end) {
+        logger.atFine().log("nextA >= end: nextA = %d, end = %d", nextA, end);
         return;
       }
 
       while (nextA < end) {
+        logger.atFine().log("nextA < end: nextA = %d, end = %d", nextA, end);
+
         if (!fileA.contains(nextA)) {
+          logger.atFine().log("fileA does not contain nextA: nextA = %d", nextA);
+
           int endRegion = Math.min(end, nextA == 0 ? fileA.first() : fileA.next(nextA - 1));
           int len = endRegion - nextA;
           entry().skip = len;
           nextA = endRegion;
           nextB += len;
+
+          logger.atFine().log("setting: nextA = %d, nextB = %d", nextA, nextB);
           continue;
         }
 
@@ -333,6 +359,7 @@
         for (int i = nextA; i == nextA && i < end; i = fileA.next(i), nextA++, nextB++) {
           if (ignoreWS && fileB.contains(nextB)) {
             if (e == null || e.common == null) {
+              logger.atFine().log("create new common entry: nextA = %d, nextB = %d", nextA, nextB);
               e = entry();
               e.a = Lists.newArrayListWithCapacity(end - nextA);
               e.b = Lists.newArrayListWithCapacity(end - nextA);
@@ -342,48 +369,71 @@
             e.b.add(fileB.get(nextB));
           } else {
             if (e == null || e.common != null) {
+              logger.atFine().log(
+                  "create new non-common entry: nextA = %d, nextB = %d", nextA, nextB);
               e = entry();
               e.ab = Lists.newArrayListWithCapacity(end - nextA);
             }
             e.ab.add(fileA.get(nextA));
           }
         }
+        logger.atFine().log("nextA = %d, nextB = %d", nextA, nextB);
       }
     }
 
     void addDiff(int endA, int endB, List<Edit> internalEdit, boolean dueToRebase) {
+      logger.atFine().log(
+          "addDiff: endA = %d, endB = %d, numberOfInternalEdits = %d, dueToRebase = %s",
+          endA, endB, internalEdit != null ? internalEdit.size() : 0, dueToRebase);
+
       int lenA = endA - nextA;
       int lenB = endB - nextB;
+      logger.atFine().log("lenA = %d, lenB = %d", lenA, lenB);
       checkState(lenA > 0 || lenB > 0);
 
+      logger.atFine().log("create non-common entry");
       ContentEntry e = entry();
       if (lenA > 0) {
+        logger.atFine().log("lenA > 0: lenA = %d", lenA);
         e.a = Lists.newArrayListWithCapacity(lenA);
         for (; nextA < endA; nextA++) {
           e.a.add(fileA.get(nextA));
         }
       }
       if (lenB > 0) {
+        logger.atFine().log("lenB > 0: lenB = %d", lenB);
         e.b = Lists.newArrayListWithCapacity(lenB);
         for (; nextB < endB; nextB++) {
           e.b.add(fileB.get(nextB));
         }
       }
       if (internalEdit != null && !internalEdit.isEmpty()) {
+        logger.atFine().log("processing internal edits");
+
         e.editA = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
         e.editB = Lists.newArrayListWithCapacity(internalEdit.size() * 2);
         int lastA = 0;
         int lastB = 0;
         for (Edit edit : internalEdit) {
+          logger.atFine().log("internal edit = %s", edit);
+
           if (edit.getBeginA() != edit.getEndA()) {
+            logger.atFine().log(
+                "edit.getBeginA() != edit.getEndA(): edit.getBeginA() = %d, edit.getEndA() = %d",
+                edit.getBeginA(), edit.getEndA());
             e.editA.add(
                 ImmutableList.of(edit.getBeginA() - lastA, edit.getEndA() - edit.getBeginA()));
             lastA = edit.getEndA();
+            logger.atFine().log("lastA = %d", lastA);
           }
           if (edit.getBeginB() != edit.getEndB()) {
+            logger.atFine().log(
+                "edit.getBeginB() != edit.getEndB(): edit.getBeginB() = %d, edit.getEndB() = %d",
+                edit.getBeginB(), edit.getEndB());
             e.editB.add(
                 ImmutableList.of(edit.getBeginB() - lastB, edit.getEndB() - edit.getBeginB()));
             lastB = edit.getEndB();
+            logger.atFine().log("lastB = %d", lastB);
           }
         }
       }
diff --git a/java/com/google/gerrit/server/restapi/change/QueryChanges.java b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
index 50e1e42..544177f 100644
--- a/java/com/google/gerrit/server/restapi/change/QueryChanges.java
+++ b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
@@ -34,9 +34,11 @@
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryProcessor;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.List;
 import org.kohsuke.args4j.Option;
 
@@ -45,8 +47,12 @@
 
   private final ChangeJson.Factory json;
   private final ChangeQueryBuilder qb;
-  private final ChangeQueryProcessor imp;
+  private final Provider<ChangeQueryProcessor> queryProcessorProvider;
+  private final HashMap<String, DynamicOptions.DynamicBean> dynamicBeans = new HashMap<>();
   private EnumSet<ListChangesOption> options;
+  private Integer limit;
+  private Integer start;
+  private Boolean noLimit;
 
   @Option(
       name = "--query",
@@ -61,7 +67,7 @@
       metaVar = "CNT",
       usage = "Maximum number of results to return")
   public void setLimit(int limit) {
-    imp.setUserProvidedLimit(limit);
+    this.limit = limit;
   }
 
   @Option(name = "-o", usage = "Output options per change")
@@ -80,24 +86,27 @@
       metaVar = "CNT",
       usage = "Number of changes to skip")
   public void setStart(int start) {
-    imp.setStart(start);
+    this.start = start;
   }
 
   @Option(name = "--no-limit", usage = "Return all results, overriding the default limit")
   public void setNoLimit(boolean on) {
-    imp.setNoLimit(on);
+    this.noLimit = on;
   }
 
   @Override
   public void setDynamicBean(String plugin, DynamicOptions.DynamicBean dynamicBean) {
-    imp.setDynamicBean(plugin, dynamicBean);
+    dynamicBeans.put(plugin, dynamicBean);
   }
 
   @Inject
-  QueryChanges(ChangeJson.Factory json, ChangeQueryBuilder qb, ChangeQueryProcessor qp) {
+  QueryChanges(
+      ChangeJson.Factory json,
+      ChangeQueryBuilder qb,
+      Provider<ChangeQueryProcessor> queryProcessorProvider) {
     this.json = json;
     this.qb = qb;
-    this.imp = qp;
+    this.queryProcessorProvider = queryProcessorProvider;
 
     options = EnumSet.noneOf(ListChangesOption.class);
   }
@@ -129,9 +138,22 @@
   }
 
   private List<List<ChangeInfo>> query() throws QueryParseException, PermissionBackendException {
-    if (imp.isDisabled()) {
+    ChangeQueryProcessor queryProcessor = queryProcessorProvider.get();
+    if (queryProcessor.isDisabled()) {
       throw new QueryParseException("query disabled");
     }
+
+    if (limit != null) {
+      queryProcessor.setUserProvidedLimit(limit);
+    }
+    if (start != null) {
+      queryProcessor.setStart(start);
+    }
+    if (noLimit != null) {
+      queryProcessor.setNoLimit(noLimit);
+    }
+    dynamicBeans.forEach((p, b) -> queryProcessor.setDynamicBean(p, b));
+
     if (queries == null || queries.isEmpty()) {
       queries = Collections.singletonList("status:open");
     } else if (queries.size() > 10) {
@@ -141,9 +163,9 @@
     }
 
     int cnt = queries.size();
-    List<QueryResult<ChangeData>> results = imp.query(qb.parse(queries));
+    List<QueryResult<ChangeData>> results = queryProcessor.query(qb.parse(queries));
     List<List<ChangeInfo>> res =
-        json.create(options, this.imp.getAttributesFactory()).format(results);
+        json.create(options, queryProcessor.getAttributesFactory()).format(results);
     for (int n = 0; n < cnt; n++) {
       List<ChangeInfo> info = res.get(n);
       if (results.get(n).more() && !info.isEmpty()) {
diff --git a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
index 7ba9b98..47c6a7e 100644
--- a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
+++ b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
@@ -160,7 +160,7 @@
             "Revert this change and all changes that have been submitted together with this change")
         .setVisible(
             and(
-                change.isMerged() && projectStatePermitsWrite,
+                change.isMerged() && change.getSubmissionId() != null && projectStatePermitsWrite,
                 permissionBackend
                     .user(rsrc.getUser())
                     .ref(change.getDest())
diff --git a/java/com/google/gerrit/server/restapi/group/GroupsCollection.java b/java/com/google/gerrit/server/restapi/group/GroupsCollection.java
index 52fe9d0..65a7f4f 100644
--- a/java/com/google/gerrit/server/restapi/group/GroupsCollection.java
+++ b/java/com/google/gerrit/server/restapi/group/GroupsCollection.java
@@ -42,7 +42,7 @@
   private final GroupResolver groupResolver;
   private final Provider<CurrentUser> self;
 
-  private boolean hasQuery2;
+  private boolean hasQuery;
 
   @Inject
   public GroupsCollection(
@@ -62,12 +62,7 @@
 
   @Override
   public void setParams(ListMultimap<String, String> params) throws BadRequestException {
-    if (params.containsKey("query") && params.containsKey("query2")) {
-      throw new BadRequestException("\"query\" and \"query2\" options are mutually exclusive");
-    }
-
-    // The --query2 option is defined in QueryGroups
-    this.hasQuery2 = params.containsKey("query2");
+    this.hasQuery = params.containsKey("query");
   }
 
   @Override
@@ -79,7 +74,7 @@
       throw new ResourceNotFoundException();
     }
 
-    if (hasQuery2) {
+    if (hasQuery) {
       return queryGroups.get();
     }
 
diff --git a/java/com/google/gerrit/server/restapi/group/ListGroups.java b/java/com/google/gerrit/server/restapi/group/ListGroups.java
index 899ed00..adc251c 100644
--- a/java/com/google/gerrit/server/restapi/group/ListGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/ListGroups.java
@@ -129,21 +129,6 @@
     this.owned = owned;
   }
 
-  /**
-   * Add a group to inspect.
-   *
-   * @param uuid UUID of the group
-   * @deprecated use {@link #addGroup(AccountGroup.UUID)}.
-   */
-  @Deprecated
-  @Option(
-      name = "--query",
-      aliases = {"-q"},
-      usage = "group to inspect (deprecated: use --group/-g instead)")
-  void addGroup_Deprecated(AccountGroup.UUID uuid) {
-    addGroup(uuid);
-  }
-
   @Option(
       name = "--group",
       aliases = {"-g"},
diff --git a/java/com/google/gerrit/server/restapi/group/QueryGroups.java b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
index 816fcf6..380d42e 100644
--- a/java/com/google/gerrit/server/restapi/group/QueryGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
@@ -32,6 +32,7 @@
 import com.google.gerrit.server.query.group.GroupQueryBuilder;
 import com.google.gerrit.server.query.group.GroupQueryProcessor;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
@@ -39,7 +40,7 @@
 
 public class QueryGroups implements RestReadView<TopLevelResource> {
   private final GroupQueryBuilder queryBuilder;
-  private final GroupQueryProcessor queryProcessor;
+  private final Provider<GroupQueryProcessor> queryProcessorProvider;
   private final GroupJson json;
 
   private String query;
@@ -47,12 +48,9 @@
   private int start;
   private EnumSet<ListGroupsOption> options = EnumSet.noneOf(ListGroupsOption.class);
 
-  // TODO(ekempin): --query in ListGroups is marked as deprecated, once it is
-  // removed we want to rename --query2 to --query here.
-  /** --query (-q) is already used by {@link ListGroups} */
   @Option(
-      name = "--query2",
-      aliases = {"-q2"},
+      name = "--query",
+      aliases = {"-q"},
       usage = "group query")
   public void setQuery(String query) {
     this.query = query;
@@ -88,9 +86,11 @@
 
   @Inject
   protected QueryGroups(
-      GroupQueryBuilder queryBuilder, GroupQueryProcessor queryProcessor, GroupJson json) {
+      GroupQueryBuilder queryBuilder,
+      Provider<GroupQueryProcessor> queryProcessorProvider,
+      GroupJson json) {
     this.queryBuilder = queryBuilder;
-    this.queryProcessor = queryProcessor;
+    this.queryProcessorProvider = queryProcessorProvider;
     this.json = json;
   }
 
@@ -101,6 +101,8 @@
       throw new BadRequestException("missing query field");
     }
 
+    GroupQueryProcessor queryProcessor = queryProcessorProvider.get();
+
     if (queryProcessor.isDisabled()) {
       throw new MethodNotAllowedException("query disabled");
     }
diff --git a/java/com/google/gerrit/server/restapi/project/CreateLabel.java b/java/com/google/gerrit/server/restapi/project/CreateLabel.java
index 03b9452..5d51527 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateLabel.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateLabel.java
@@ -91,85 +91,7 @@
     try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) {
       ProjectConfig config = projectConfigFactory.read(md);
 
-      if (config.getLabelSections().containsKey(id.get())) {
-        throw new ResourceConflictException(String.format("label %s already exists", id.get()));
-      }
-
-      for (String labelName : config.getLabelSections().keySet()) {
-        if (labelName.equalsIgnoreCase(id.get())) {
-          throw new ResourceConflictException(
-              String.format("label %s conflicts with existing label %s", id.get(), labelName));
-        }
-      }
-
-      if (input.values == null || input.values.isEmpty()) {
-        throw new BadRequestException("values are required");
-      }
-
-      List<LabelValue> values = LabelDefinitionInputParser.parseValues(input.values);
-
-      LabelType labelType;
-      try {
-        labelType = new LabelType(id.get(), values);
-      } catch (IllegalArgumentException e) {
-        throw new BadRequestException("invalid name: " + id.get(), e);
-      }
-
-      if (input.function != null && !input.function.trim().isEmpty()) {
-        labelType.setFunction(LabelDefinitionInputParser.parseFunction(input.function));
-      } else {
-        labelType.setFunction(LabelFunction.MAX_WITH_BLOCK);
-      }
-
-      if (input.defaultValue != null) {
-        labelType.setDefaultValue(
-            LabelDefinitionInputParser.parseDefaultValue(labelType, input.defaultValue));
-      }
-
-      if (input.branches != null) {
-        labelType.setRefPatterns(LabelDefinitionInputParser.parseBranches(input.branches));
-      }
-
-      if (input.canOverride != null) {
-        labelType.setCanOverride(input.canOverride);
-      }
-
-      if (input.copyAnyScore != null) {
-        labelType.setCopyAnyScore(input.copyAnyScore);
-      }
-
-      if (input.copyMinScore != null) {
-        labelType.setCopyMinScore(input.copyMinScore);
-      }
-
-      if (input.copyMaxScore != null) {
-        labelType.setCopyMaxScore(input.copyMaxScore);
-      }
-
-      if (input.copyAllScoresIfNoChange != null) {
-        labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
-      }
-
-      if (input.copyAllScoresIfNoCodeChange != null) {
-        labelType.setCopyAllScoresIfNoCodeChange(input.copyAllScoresIfNoCodeChange);
-      }
-
-      if (input.copyAllScoresOnTrivialRebase != null) {
-        labelType.setCopyAllScoresOnTrivialRebase(input.copyAllScoresOnTrivialRebase);
-      }
-
-      if (input.copyAllScoresOnMergeFirstParentUpdate != null) {
-        labelType.setCopyAllScoresOnMergeFirstParentUpdate(
-            input.copyAllScoresOnMergeFirstParentUpdate);
-      }
-
-      if (input.allowPostSubmit != null) {
-        labelType.setAllowPostSubmit(input.allowPostSubmit);
-      }
-
-      if (input.ignoreSelfApproval != null) {
-        labelType.setIgnoreSelfApproval(input.ignoreSelfApproval);
-      }
+      LabelType labelType = createLabel(config, id.get(), input);
 
       if (input.commitMessage != null) {
         md.setMessage(Strings.emptyToNull(input.commitMessage.trim()));
@@ -177,7 +99,6 @@
         md.setMessage("Update label");
       }
 
-      config.getLabelSections().put(labelType.getName(), labelType);
       config.commit(md);
 
       projectCache.evict(rsrc.getProjectState().getProject());
@@ -185,4 +106,101 @@
       return Response.created(LabelDefinitionJson.format(rsrc.getNameKey(), labelType));
     }
   }
+
+  /**
+   * Creates a new label.
+   *
+   * @param config the project config
+   * @param label the name of the new label
+   * @param input the input that describes the new label
+   * @return the created label type
+   * @throws BadRequestException if there was invalid data in the input
+   * @throws ResourceConflictException if the label cannot be created due to a conflict
+   */
+  public LabelType createLabel(ProjectConfig config, String label, LabelDefinitionInput input)
+      throws BadRequestException, ResourceConflictException {
+    if (config.getLabelSections().containsKey(label)) {
+      throw new ResourceConflictException(String.format("label %s already exists", label));
+    }
+
+    for (String labelName : config.getLabelSections().keySet()) {
+      if (labelName.equalsIgnoreCase(label)) {
+        throw new ResourceConflictException(
+            String.format("label %s conflicts with existing label %s", label, labelName));
+      }
+    }
+
+    if (input.values == null || input.values.isEmpty()) {
+      throw new BadRequestException("values are required");
+    }
+
+    List<LabelValue> values = LabelDefinitionInputParser.parseValues(input.values);
+
+    LabelType labelType;
+    try {
+      labelType = new LabelType(label, values);
+    } catch (IllegalArgumentException e) {
+      throw new BadRequestException("invalid name: " + label, e);
+    }
+
+    if (input.function != null && !input.function.trim().isEmpty()) {
+      labelType.setFunction(LabelDefinitionInputParser.parseFunction(input.function));
+    } else {
+      labelType.setFunction(LabelFunction.MAX_WITH_BLOCK);
+    }
+
+    if (input.defaultValue != null) {
+      labelType.setDefaultValue(
+          LabelDefinitionInputParser.parseDefaultValue(labelType, input.defaultValue));
+    }
+
+    if (input.branches != null) {
+      labelType.setRefPatterns(LabelDefinitionInputParser.parseBranches(input.branches));
+    }
+
+    if (input.canOverride != null) {
+      labelType.setCanOverride(input.canOverride);
+    }
+
+    if (input.copyAnyScore != null) {
+      labelType.setCopyAnyScore(input.copyAnyScore);
+    }
+
+    if (input.copyMinScore != null) {
+      labelType.setCopyMinScore(input.copyMinScore);
+    }
+
+    if (input.copyMaxScore != null) {
+      labelType.setCopyMaxScore(input.copyMaxScore);
+    }
+
+    if (input.copyAllScoresIfNoChange != null) {
+      labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
+    }
+
+    if (input.copyAllScoresIfNoCodeChange != null) {
+      labelType.setCopyAllScoresIfNoCodeChange(input.copyAllScoresIfNoCodeChange);
+    }
+
+    if (input.copyAllScoresOnTrivialRebase != null) {
+      labelType.setCopyAllScoresOnTrivialRebase(input.copyAllScoresOnTrivialRebase);
+    }
+
+    if (input.copyAllScoresOnMergeFirstParentUpdate != null) {
+      labelType.setCopyAllScoresOnMergeFirstParentUpdate(
+          input.copyAllScoresOnMergeFirstParentUpdate);
+    }
+
+    if (input.allowPostSubmit != null) {
+      labelType.setAllowPostSubmit(input.allowPostSubmit);
+    }
+
+    if (input.ignoreSelfApproval != null) {
+      labelType.setIgnoreSelfApproval(input.ignoreSelfApproval);
+    }
+
+    config.getLabelSections().put(labelType.getName(), labelType);
+
+    return labelType;
+  }
 }
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteBranch.java b/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
index 2a20283..6248a61 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
@@ -17,6 +17,7 @@
 import static com.google.gerrit.entities.RefNames.isConfigRef;
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.common.Input;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
@@ -46,7 +47,9 @@
   @Override
   public Response<?> apply(BranchResource rsrc, Input input)
       throws RestApiException, IOException, PermissionBackendException {
-    if (isConfigRef(rsrc.getBranchKey().branch())) {
+    if (RefNames.HEAD.equals(rsrc.getBranchKey().branch())) {
+      throw new MethodNotAllowedException("not allowed to delete HEAD");
+    } else if (isConfigRef(rsrc.getBranchKey().branch())) {
       // Never allow to delete the meta config branch.
       throw new MethodNotAllowedException(
           "not allowed to delete branch " + rsrc.getBranchKey().branch());
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteBranches.java b/java/com/google/gerrit/server/restapi/project/DeleteBranches.java
index d429655..ca5962e 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteBranches.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteBranches.java
@@ -17,8 +17,10 @@
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.api.projects.DeleteBranchesInput;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
@@ -43,6 +45,14 @@
     if (input == null || input.branches == null || input.branches.isEmpty()) {
       throw new BadRequestException("branches must be specified");
     }
+
+    if (input.branches.contains(RefNames.HEAD)) {
+      throw new MethodNotAllowedException("not allowed to delete HEAD");
+    } else if (input.branches.stream().anyMatch(RefNames::isConfigRef)) {
+      // Never allow to delete the meta config branch.
+      throw new MethodNotAllowedException("not allowed to delete branch " + RefNames.REFS_CONFIG);
+    }
+
     deleteRef.deleteMultipleRefs(
         project.getProjectState(), ImmutableSet.copyOf(input.branches), R_HEADS);
     return Response.none();
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteLabel.java b/java/com/google/gerrit/server/restapi/project/DeleteLabel.java
index 5464abf..531640c 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteLabel.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteLabel.java
@@ -77,12 +77,10 @@
     try (MetaDataUpdate md = updateFactory.create(rsrc.getProject().getNameKey())) {
       ProjectConfig config = projectConfigFactory.read(md);
 
-      if (!config.getLabelSections().containsKey(rsrc.getLabelType().getName())) {
+      if (!deleteLabel(config, rsrc.getLabelType().getName())) {
         throw new ResourceNotFoundException(IdString.fromDecoded(rsrc.getLabelType().getName()));
       }
 
-      config.getLabelSections().remove(rsrc.getLabelType().getName());
-
       if (input.commitMessage != null) {
         md.setMessage(Strings.emptyToNull(input.commitMessage.trim()));
       } else {
@@ -96,4 +94,20 @@
 
     return Response.none();
   }
+
+  /**
+   * Delete the given label from the given project config.
+   *
+   * @param config the project config from which the label should be deleted
+   * @param labelName the name of the label that should be deleted
+   * @return {@code true} if the label was deleted, {@code false} if the label was not found
+   */
+  public boolean deleteLabel(ProjectConfig config, String labelName) {
+    if (!config.getLabelSections().containsKey(labelName)) {
+      return false;
+    }
+
+    config.getLabelSections().remove(labelName);
+    return true;
+  }
 }
diff --git a/java/com/google/gerrit/server/restapi/project/Module.java b/java/com/google/gerrit/server/restapi/project/Module.java
index 2c76cbd..5b3ea30 100644
--- a/java/com/google/gerrit/server/restapi/project/Module.java
+++ b/java/com/google/gerrit/server/restapi/project/Module.java
@@ -72,6 +72,7 @@
     get(LABEL_KIND).to(GetLabel.class);
     put(LABEL_KIND).to(SetLabel.class);
     delete(LABEL_KIND).to(DeleteLabel.class);
+    postOnCollection(LABEL_KIND).to(PostLabels.class);
 
     get(PROJECT_KIND, "HEAD").to(GetHead.class);
     put(PROJECT_KIND, "HEAD").to(SetHead.class);
diff --git a/java/com/google/gerrit/server/restapi/project/PostLabels.java b/java/com/google/gerrit/server/restapi/project/PostLabels.java
new file mode 100644
index 0000000..8835359
--- /dev/null
+++ b/java/com/google/gerrit/server/restapi/project/PostLabels.java
@@ -0,0 +1,148 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.restapi.project;
+
+import com.google.common.base.Strings;
+import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.extensions.common.BatchLabelInput;
+import com.google.gerrit.extensions.common.LabelDefinitionInput;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestCollectionModifyView;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.permissions.ProjectPermission;
+import com.google.gerrit.server.project.LabelResource;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
+import com.google.gerrit.server.project.ProjectResource;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import java.util.Map.Entry;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+
+/** REST endpoint that allows to add, update and delete label definitions in a batch. */
+@Singleton
+public class PostLabels
+    implements RestCollectionModifyView<ProjectResource, LabelResource, BatchLabelInput> {
+  private final Provider<CurrentUser> user;
+  private final PermissionBackend permissionBackend;
+  private final MetaDataUpdate.User updateFactory;
+  private final ProjectConfig.Factory projectConfigFactory;
+  private final DeleteLabel deleteLabel;
+  private final CreateLabel createLabel;
+  private final SetLabel setLabel;
+  private final ProjectCache projectCache;
+
+  @Inject
+  public PostLabels(
+      Provider<CurrentUser> user,
+      PermissionBackend permissionBackend,
+      MetaDataUpdate.User updateFactory,
+      ProjectConfig.Factory projectConfigFactory,
+      DeleteLabel deleteLabel,
+      CreateLabel createLabel,
+      SetLabel setLabel,
+      ProjectCache projectCache) {
+    this.user = user;
+    this.permissionBackend = permissionBackend;
+    this.updateFactory = updateFactory;
+    this.projectConfigFactory = projectConfigFactory;
+    this.deleteLabel = deleteLabel;
+    this.createLabel = createLabel;
+    this.setLabel = setLabel;
+    this.projectCache = projectCache;
+  }
+
+  @Override
+  public Response<?> apply(ProjectResource rsrc, BatchLabelInput input)
+      throws AuthException, UnprocessableEntityException, PermissionBackendException, IOException,
+          ConfigInvalidException, BadRequestException, ResourceConflictException {
+    if (!user.get().isIdentifiedUser()) {
+      throw new AuthException("Authentication required");
+    }
+
+    permissionBackend
+        .currentUser()
+        .project(rsrc.getNameKey())
+        .check(ProjectPermission.WRITE_CONFIG);
+
+    if (input == null) {
+      input = new BatchLabelInput();
+    }
+
+    try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) {
+      boolean dirty = false;
+
+      ProjectConfig config = projectConfigFactory.read(md);
+
+      if (input.delete != null && !input.delete.isEmpty()) {
+        for (String labelName : input.delete) {
+          if (!deleteLabel.deleteLabel(config, labelName.trim())) {
+            throw new UnprocessableEntityException(String.format("label %s not found", labelName));
+          }
+        }
+        dirty = true;
+      }
+
+      if (input.create != null && !input.create.isEmpty()) {
+        for (LabelDefinitionInput labelInput : input.create) {
+          if (labelInput.name == null || labelInput.name.trim().isEmpty()) {
+            throw new BadRequestException("label name is required for new label");
+          }
+          if (labelInput.commitMessage != null) {
+            throw new BadRequestException("commit message on label definition input not supported");
+          }
+          createLabel.createLabel(config, labelInput.name.trim(), labelInput);
+        }
+        dirty = true;
+      }
+
+      if (input.update != null && !input.update.isEmpty()) {
+        for (Entry<String, LabelDefinitionInput> e : input.update.entrySet()) {
+          LabelType labelType = config.getLabelSections().get(e.getKey().trim());
+          if (labelType == null) {
+            throw new UnprocessableEntityException(String.format("label %s not found", e.getKey()));
+          }
+          if (e.getValue().commitMessage != null) {
+            throw new BadRequestException("commit message on label definition input not supported");
+          }
+          setLabel.updateLabel(config, labelType, e.getValue());
+        }
+        dirty = true;
+      }
+
+      if (input.commitMessage != null) {
+        md.setMessage(Strings.emptyToNull(input.commitMessage.trim()));
+      } else {
+        md.setMessage("Update labels");
+      }
+
+      if (dirty) {
+        config.commit(md);
+        projectCache.evict(rsrc.getProjectState().getProject());
+      }
+    }
+
+    return Response.ok("");
+  }
+}
diff --git a/java/com/google/gerrit/server/restapi/project/QueryProjects.java b/java/com/google/gerrit/server/restapi/project/QueryProjects.java
index 7066d9a..e4f7df5 100644
--- a/java/com/google/gerrit/server/restapi/project/QueryProjects.java
+++ b/java/com/google/gerrit/server/restapi/project/QueryProjects.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.server.query.project.ProjectQueryBuilder;
 import com.google.gerrit.server.query.project.ProjectQueryProcessor;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import java.util.ArrayList;
 import java.util.List;
 import org.kohsuke.args4j.Option;
@@ -38,7 +39,7 @@
 public class QueryProjects implements RestReadView<TopLevelResource> {
   private final ProjectIndexCollection indexes;
   private final ProjectQueryBuilder queryBuilder;
-  private final ProjectQueryProcessor queryProcessor;
+  private final Provider<ProjectQueryProcessor> queryProcessorProvider;
   private final ProjectJson json;
 
   private String query;
@@ -78,11 +79,11 @@
   protected QueryProjects(
       ProjectIndexCollection indexes,
       ProjectQueryBuilder queryBuilder,
-      ProjectQueryProcessor queryProcessor,
+      Provider<ProjectQueryProcessor> queryProcessorProvider,
       ProjectJson json) {
     this.indexes = indexes;
     this.queryBuilder = queryBuilder;
-    this.queryProcessor = queryProcessor;
+    this.queryProcessorProvider = queryProcessorProvider;
     this.json = json;
   }
 
@@ -102,6 +103,8 @@
       throw new MethodNotAllowedException("no project index");
     }
 
+    ProjectQueryProcessor queryProcessor = queryProcessorProvider.get();
+
     if (start != 0) {
       queryProcessor.setStart(start);
     }
diff --git a/java/com/google/gerrit/server/restapi/project/SetLabel.java b/java/com/google/gerrit/server/restapi/project/SetLabel.java
index b7cffce..824b4ed 100644
--- a/java/com/google/gerrit/server/restapi/project/SetLabel.java
+++ b/java/com/google/gerrit/server/restapi/project/SetLabel.java
@@ -80,117 +80,9 @@
     LabelType labelType = rsrc.getLabelType();
 
     try (MetaDataUpdate md = updateFactory.create(rsrc.getProject().getNameKey())) {
-      boolean dirty = false;
-
       ProjectConfig config = projectConfigFactory.read(md);
-      config.getLabelSections().remove(labelType.getName());
 
-      if (input.name != null) {
-        String newName = input.name.trim();
-        if (newName.isEmpty()) {
-          throw new BadRequestException("name cannot be empty");
-        }
-        if (!newName.equals(labelType.getName())) {
-          if (config.getLabelSections().containsKey(newName)) {
-            throw new ResourceConflictException(String.format("name %s already in use", newName));
-          }
-
-          for (String labelName : config.getLabelSections().keySet()) {
-            if (labelName.equalsIgnoreCase(newName)) {
-              throw new ResourceConflictException(
-                  String.format("name %s conflicts with existing label %s", newName, labelName));
-            }
-          }
-
-          try {
-            labelType.setName(newName);
-          } catch (IllegalArgumentException e) {
-            throw new BadRequestException("invalid name: " + input.name, e);
-          }
-          dirty = true;
-        }
-      }
-
-      if (input.function != null) {
-        if (input.function.trim().isEmpty()) {
-          throw new BadRequestException("function cannot be empty");
-        }
-        labelType.setFunction(LabelDefinitionInputParser.parseFunction(input.function));
-        dirty = true;
-      }
-
-      if (input.values != null) {
-        if (input.values.isEmpty()) {
-          throw new BadRequestException("values cannot be empty");
-        }
-        labelType.setValues(LabelDefinitionInputParser.parseValues(input.values));
-        dirty = true;
-      }
-
-      if (input.defaultValue != null) {
-        labelType.setDefaultValue(
-            LabelDefinitionInputParser.parseDefaultValue(labelType, input.defaultValue));
-        dirty = true;
-      }
-
-      if (input.branches != null) {
-        labelType.setRefPatterns(LabelDefinitionInputParser.parseBranches(input.branches));
-        dirty = true;
-      }
-
-      if (input.canOverride != null) {
-        labelType.setCanOverride(input.canOverride);
-        dirty = true;
-      }
-
-      if (input.copyAnyScore != null) {
-        labelType.setCopyAnyScore(input.copyAnyScore);
-        dirty = true;
-      }
-
-      if (input.copyMinScore != null) {
-        labelType.setCopyMinScore(input.copyMinScore);
-        dirty = true;
-      }
-
-      if (input.copyMaxScore != null) {
-        labelType.setCopyMaxScore(input.copyMaxScore);
-        dirty = true;
-      }
-
-      if (input.copyAllScoresIfNoChange != null) {
-        labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
-      }
-
-      if (input.copyAllScoresIfNoCodeChange != null) {
-        labelType.setCopyAllScoresIfNoCodeChange(input.copyAllScoresIfNoCodeChange);
-        dirty = true;
-      }
-
-      if (input.copyAllScoresOnTrivialRebase != null) {
-        labelType.setCopyAllScoresOnTrivialRebase(input.copyAllScoresOnTrivialRebase);
-        dirty = true;
-      }
-
-      if (input.copyAllScoresOnMergeFirstParentUpdate != null) {
-        labelType.setCopyAllScoresOnMergeFirstParentUpdate(
-            input.copyAllScoresOnMergeFirstParentUpdate);
-        dirty = true;
-      }
-
-      if (input.allowPostSubmit != null) {
-        labelType.setAllowPostSubmit(input.allowPostSubmit);
-        dirty = true;
-      }
-
-      if (input.ignoreSelfApproval != null) {
-        labelType.setIgnoreSelfApproval(input.ignoreSelfApproval);
-        dirty = true;
-      }
-
-      if (dirty) {
-        config.getLabelSections().put(labelType.getName(), labelType);
-
+      if (updateLabel(config, labelType, input)) {
         if (input.commitMessage != null) {
           md.setMessage(Strings.emptyToNull(input.commitMessage.trim()));
         } else {
@@ -203,4 +95,128 @@
     }
     return Response.ok(LabelDefinitionJson.format(rsrc.getProject().getNameKey(), labelType));
   }
+
+  /**
+   * Updates the given label.
+   *
+   * @param config the project config
+   * @param labelType the label type that should be updated
+   * @param input the input that describes the label update
+   * @return whether the label type was modified
+   * @throws BadRequestException if there was invalid data in the input
+   * @throws ResourceConflictException if the update cannot be applied due to a conflict
+   */
+  public boolean updateLabel(ProjectConfig config, LabelType labelType, LabelDefinitionInput input)
+      throws BadRequestException, ResourceConflictException {
+    boolean dirty = false;
+
+    config.getLabelSections().remove(labelType.getName());
+
+    if (input.name != null) {
+      String newName = input.name.trim();
+      if (newName.isEmpty()) {
+        throw new BadRequestException("name cannot be empty");
+      }
+      if (!newName.equals(labelType.getName())) {
+        if (config.getLabelSections().containsKey(newName)) {
+          throw new ResourceConflictException(String.format("name %s already in use", newName));
+        }
+
+        for (String labelName : config.getLabelSections().keySet()) {
+          if (labelName.equalsIgnoreCase(newName)) {
+            throw new ResourceConflictException(
+                String.format("name %s conflicts with existing label %s", newName, labelName));
+          }
+        }
+
+        try {
+          labelType.setName(newName);
+        } catch (IllegalArgumentException e) {
+          throw new BadRequestException("invalid name: " + input.name, e);
+        }
+        dirty = true;
+      }
+    }
+
+    if (input.function != null) {
+      if (input.function.trim().isEmpty()) {
+        throw new BadRequestException("function cannot be empty");
+      }
+      labelType.setFunction(LabelDefinitionInputParser.parseFunction(input.function));
+      dirty = true;
+    }
+
+    if (input.values != null) {
+      if (input.values.isEmpty()) {
+        throw new BadRequestException("values cannot be empty");
+      }
+      labelType.setValues(LabelDefinitionInputParser.parseValues(input.values));
+      dirty = true;
+    }
+
+    if (input.defaultValue != null) {
+      labelType.setDefaultValue(
+          LabelDefinitionInputParser.parseDefaultValue(labelType, input.defaultValue));
+      dirty = true;
+    }
+
+    if (input.branches != null) {
+      labelType.setRefPatterns(LabelDefinitionInputParser.parseBranches(input.branches));
+      dirty = true;
+    }
+
+    if (input.canOverride != null) {
+      labelType.setCanOverride(input.canOverride);
+      dirty = true;
+    }
+
+    if (input.copyAnyScore != null) {
+      labelType.setCopyAnyScore(input.copyAnyScore);
+      dirty = true;
+    }
+
+    if (input.copyMinScore != null) {
+      labelType.setCopyMinScore(input.copyMinScore);
+      dirty = true;
+    }
+
+    if (input.copyMaxScore != null) {
+      labelType.setCopyMaxScore(input.copyMaxScore);
+      dirty = true;
+    }
+
+    if (input.copyAllScoresIfNoChange != null) {
+      labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
+    }
+
+    if (input.copyAllScoresIfNoCodeChange != null) {
+      labelType.setCopyAllScoresIfNoCodeChange(input.copyAllScoresIfNoCodeChange);
+      dirty = true;
+    }
+
+    if (input.copyAllScoresOnTrivialRebase != null) {
+      labelType.setCopyAllScoresOnTrivialRebase(input.copyAllScoresOnTrivialRebase);
+      dirty = true;
+    }
+
+    if (input.copyAllScoresOnMergeFirstParentUpdate != null) {
+      labelType.setCopyAllScoresOnMergeFirstParentUpdate(
+          input.copyAllScoresOnMergeFirstParentUpdate);
+      dirty = true;
+    }
+
+    if (input.allowPostSubmit != null) {
+      labelType.setAllowPostSubmit(input.allowPostSubmit);
+      dirty = true;
+    }
+
+    if (input.ignoreSelfApproval != null) {
+      labelType.setIgnoreSelfApproval(input.ignoreSelfApproval);
+      dirty = true;
+    }
+
+    config.getLabelSections().put(labelType.getName(), labelType);
+
+    return dirty;
+  }
 }
diff --git a/java/com/google/gerrit/server/submit/MergeSuperSet.java b/java/com/google/gerrit/server/submit/MergeSuperSet.java
index c690e0b..bcebc7f 100644
--- a/java/com/google/gerrit/server/submit/MergeSuperSet.java
+++ b/java/com/google/gerrit/server/submit/MergeSuperSet.java
@@ -99,7 +99,11 @@
         closeOrm = true;
       }
       List<ChangeData> cds = queryProvider.get().byLegacyChangeId(change.getId());
-      checkState(cds.size() == 1, "Expected exactly one ChangeData, got " + cds.size());
+      checkState(
+          cds.size() == 1,
+          "Expected exactly one ChangeData for change ID %s, got %s",
+          change.getId(),
+          cds.size());
       ChangeData cd = Iterables.getFirst(cds, null);
 
       boolean visible = false;
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java
index ce16706..e240f6a 100644
--- a/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -128,23 +128,23 @@
 
     try {
       List<ListenableFuture<?>> indexFutures = new ArrayList<>();
-      List<ChangesHandle> handles = new ArrayList<>(updates.size());
+      List<ChangesHandle> changesHandles = new ArrayList<>(updates.size());
       try {
         for (BatchUpdate u : updates) {
           u.executeUpdateRepo();
         }
         listener.afterUpdateRepos();
         for (BatchUpdate u : updates) {
-          handles.add(u.executeChangeOps(dryrun));
+          changesHandles.add(u.executeChangeOps(dryrun));
         }
-        for (ChangesHandle h : handles) {
+        for (ChangesHandle h : changesHandles) {
           h.execute();
           indexFutures.addAll(h.startIndexFutures());
         }
         listener.afterUpdateRefs();
         listener.afterUpdateChanges();
       } finally {
-        for (ChangesHandle h : handles) {
+        for (ChangesHandle h : changesHandles) {
           h.close();
         }
       }
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 18e47f9..f8cf4cf 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -288,7 +288,7 @@
           () -> changeAction.call(updateFactory),
           opts,
           t -> {
-            if (t instanceof UpdateException) {
+            if (t instanceof UpdateException || t instanceof StorageException) {
               t = t.getCause();
             }
             return t instanceof LockFailureException;
@@ -378,7 +378,10 @@
   }
 
   private String formatCause(Throwable t) {
-    if (t instanceof UpdateException || t instanceof StorageException) {
+    while ((t instanceof UpdateException
+            || t instanceof StorageException
+            || t instanceof ExecutionException)
+        && t.getCause() != null) {
       t = t.getCause();
     }
 
diff --git a/java/com/google/gerrit/server/util/git/DelegateSystemReader.java b/java/com/google/gerrit/server/util/git/DelegateSystemReader.java
index 67e8dec..279bb95 100644
--- a/java/com/google/gerrit/server/util/git/DelegateSystemReader.java
+++ b/java/com/google/gerrit/server/util/git/DelegateSystemReader.java
@@ -52,6 +52,11 @@
   }
 
   @Override
+  public FileBasedConfig openJGitConfig(Config parent, FS fs) {
+    return delegate.openJGitConfig(parent, fs);
+  }
+
+  @Override
   public long getCurrentTime() {
     return delegate.getCurrentTime();
   }
diff --git a/java/com/google/gerrit/testing/BUILD b/java/com/google/gerrit/testing/BUILD
index 5e2fbea..a76275b 100644
--- a/java/com/google/gerrit/testing/BUILD
+++ b/java/com/google/gerrit/testing/BUILD
@@ -13,6 +13,7 @@
         "//lib/mockito",
     ],
     deps = [
+        "//java/com/google/gerrit/acceptance/config",
         "//java/com/google/gerrit/acceptance/testsuite/project",
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/entities",
diff --git a/java/com/google/gerrit/testing/GerritServerTests.java b/java/com/google/gerrit/testing/GerritServerTests.java
index ad985b6..363a07d 100644
--- a/java/com/google/gerrit/testing/GerritServerTests.java
+++ b/java/com/google/gerrit/testing/GerritServerTests.java
@@ -14,6 +14,9 @@
 
 package com.google.gerrit.testing;
 
+import com.google.gerrit.acceptance.config.ConfigAnnotationParser;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfigs;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Rule;
 import org.junit.rules.TestRule;
@@ -23,16 +26,24 @@
 @RunWith(ConfigSuite.class)
 public class GerritServerTests {
   @ConfigSuite.Parameter public Config config;
-
   @ConfigSuite.Name private String configName;
 
   @Rule
   public TestRule testRunner =
-      (base, description) ->
-          new Statement() {
-            @Override
-            public void evaluate() throws Throwable {
-              base.evaluate();
-            }
-          };
+      (base, description) -> {
+        GerritConfig gerritConfig = description.getAnnotation(GerritConfig.class);
+        if (gerritConfig != null) {
+          config = ConfigAnnotationParser.parse(config, gerritConfig);
+        }
+        GerritConfigs gerritConfigs = description.getAnnotation(GerritConfigs.class);
+        if (gerritConfigs != null) {
+          config = ConfigAnnotationParser.parse(config, gerritConfigs);
+        }
+        return new Statement() {
+          @Override
+          public void evaluate() throws Throwable {
+            base.evaluate();
+          }
+        };
+      };
 }
diff --git a/java/com/google/gerrit/testing/IndexConfig.java b/java/com/google/gerrit/testing/IndexConfig.java
index 21c49dd..fb6c926 100644
--- a/java/com/google/gerrit/testing/IndexConfig.java
+++ b/java/com/google/gerrit/testing/IndexConfig.java
@@ -23,7 +23,9 @@
 
   public static Config createFromExistingConfig(Config cfg) {
     cfg.setInt("index", null, "maxPages", 10);
-    cfg.setBoolean("index", null, "reindexAfterRefUpdate", false);
+    // To avoid this flakiness indexMergeable is switched off for the tests as it incurs background
+    // reindex calls.
+    cfg.setBoolean("index", "change", "indexMergeable", false);
     cfg.setString("trackingid", "query-bug", "footer", "Bug:");
     cfg.setString("trackingid", "query-bug", "match", "QUERY\\d{2,8}");
     cfg.setString("trackingid", "query-bug", "system", "querytests");
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 4ba6475..b375f22 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -59,12 +59,12 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.UseClockStep;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
index 25617d4..a09284e 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountManagerIT.java
@@ -23,7 +23,7 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.ServerInitiated;
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
index 9059cb1..3bb0338 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AgreementsIT.java
@@ -21,9 +21,9 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.RawInputUtil;
diff --git a/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java b/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
index 8aebc69..0090ed1 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/AbandonIT.java
@@ -25,9 +25,9 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.Permission;
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index f176663..7ecb07e 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -74,13 +74,13 @@
 import com.google.gerrit.acceptance.ChangeIndexedCounter;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.acceptance.UseClockStep;
 import com.google.gerrit.acceptance.UseTimezone;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
@@ -249,6 +249,7 @@
     assertThat(c.owner.email).isNull();
     assertThat(c.owner.username).isNull();
     assertThat(c.owner.avatars).isNull();
+    assertThat(c.submissionId).isNull();
   }
 
   @Test
@@ -314,6 +315,15 @@
   }
 
   @Test
+  public void getSubmissionId() throws Exception {
+    PushOneCommit.Result changeResult = createChange();
+    String changeId = changeResult.getChangeId();
+
+    merge(changeResult);
+    assertThat(gApi.changes().id(changeId).get().submissionId).isNotNull();
+  }
+
+  @Test
   public void setWorkInProgressNotAllowedWithoutPermission() throws Exception {
     PushOneCommit.Result rwip = createChange();
     String changeId = rwip.getChangeId();
@@ -3380,6 +3390,7 @@
 
     ChangeInfo change = gApi.changes().id(r.getChangeId()).get();
     assertThat(change.status).isEqualTo(ChangeStatus.MERGED);
+    assertThat(change.submissionId).isNotNull();
     assertThat(change.labels.keySet()).containsExactly("Code-Review");
     assertThat(change.permittedLabels.keySet()).containsExactly("Code-Review");
     assertPermitted(change, "Code-Review", 2);
@@ -3540,6 +3551,7 @@
 
     ChangeInfo change = gApi.changes().id(r.getChangeId()).get();
     assertThat(change.status).isEqualTo(ChangeStatus.MERGED);
+    assertThat(change.submissionId).isNotNull();
     assertThat(change.labels.keySet()).containsExactly("Code-Review", "Non-Author-Code-Review");
     assertThat(change.permittedLabels.keySet()).containsExactly("Code-Review");
     assertPermitted(change, "Code-Review", 0, 1, 2);
@@ -3555,6 +3567,7 @@
 
     ChangeInfo change = gApi.changes().id(r.getChangeId()).get();
     assertThat(change.status).isEqualTo(ChangeStatus.MERGED);
+    assertThat(change.submissionId).isNotNull();
     assertThat(change.labels.keySet()).containsExactly("Code-Review");
     assertPermitted(change, "Code-Review", 0, 1, 2);
   }
@@ -4383,6 +4396,20 @@
     }
   }
 
+  @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "true")
+  public void changeQueryReturnsMergeableWhenGerritIndexMergeable() throws Exception {
+    String changeId = createChange().getChangeId();
+    assertThat(gApi.changes().query(changeId).get().get(0).mergeable).isTrue();
+  }
+
+  @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "false")
+  public void changeQueryDoesNotReturnMergeableWhenGerritDoesNotIndexMergeable() throws Exception {
+    String changeId = createChange().getChangeId();
+    assertThat(gApi.changes().query(changeId).get().get(0).mergeable).isNull();
+  }
+
   private PushOneCommit.Result createWorkInProgressChange() throws Exception {
     return pushTo("refs/for/master%wip");
   }
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIdIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIdIT.java
index b8a4871..a0a88f8 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIdIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIdIT.java
@@ -18,8 +18,8 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
diff --git a/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java b/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
index 42d62bd..eee25b8 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/DisablePrivateChangesIT.java
@@ -18,8 +18,8 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.extensions.common.ChangeInput;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import org.junit.Test;
diff --git a/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
index d73bab0..b5d673c 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/QueryChangeIT.java
@@ -15,22 +15,32 @@
 package com.google.gerrit.acceptance.api.change;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
+import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static java.util.stream.Collectors.toList;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.server.restapi.change.QueryChanges;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import java.util.List;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
 import org.junit.Test;
 
 @NoHttpd
 public class QueryChangeIT extends AbstractDaemonTest {
-
+  @Inject private ProjectOperations projectOperations;
   @Inject private Provider<QueryChanges> queryChangesProvider;
 
   @Test
@@ -123,6 +133,68 @@
     assertThat(result.get(2).get(0)._number).isEqualTo(numericId2);
   }
 
+  @Test
+  @UseClockStep
+  @SuppressWarnings("unchecked")
+  public void withPagedResults() throws Exception {
+    // Create 4 visible changes.
+    createChange(testRepo).getChange().getId().get();
+    createChange(testRepo).getChange().getId().get();
+    int changeId3 = createChange(testRepo).getChange().getId().get();
+    int changeId4 = createChange(testRepo).getChange().getId().get();
+
+    // Create hidden project.
+    Project.NameKey hiddenProject = projectOperations.newProject().create();
+    projectOperations
+        .project(hiddenProject)
+        .forUpdate()
+        .add(block(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
+        .update();
+    TestRepository<InMemoryRepository> hiddenRepo = cloneProject(hiddenProject, admin);
+
+    // Create 2 hidden changes.
+    createChange(hiddenRepo);
+    createChange(hiddenRepo);
+
+    // Create a change query that matches all changes (visible and hidden changes).
+    // The index returns the changes ordered by last updated timestamp:
+    // hiddenChange2, hiddenChange1, change4, change3, change2, change1
+    QueryChanges queryChanges = queryChangesProvider.get();
+    queryChanges.addQuery("branch:master");
+
+    // Set a limit on the query so that we need to paginate over the results from the index.
+    queryChanges.setLimit(2);
+
+    // Execute the query and verify the results.
+    // Since the limit is set to 2, at most 2 changes are returned to user, but the index query is
+    // executed with limit 3 (+1 so that we can populate the _more_changes field on the last
+    // result).
+    // This means the index query with limit 3 returns these changes:
+    // hiddenChange2, hiddenChange1, change4
+    // The 2 hidden changes are filtered out because they are not visible to the caller.
+    // This means we have only one matching result (change4) but the limit (3) is not exhausted
+    // yet. Hence the next page is loaded from the index (startIndex is 3 to skip the results
+    // that we already processed, limit is again 3). The results for the next page are:
+    // change3, change2, change1
+    // change2 and change1 are dropped because they are over the limit.
+    List<ChangeInfo> result =
+        (List<ChangeInfo>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+    assertThat(result.stream().map(i -> i._number).collect(toList()))
+        .containsExactly(changeId3, changeId4);
+  }
+
+  @Test
+  public void usingOutOfRangeLabelValuesDoesNotCauseError() throws Exception {
+    for (String operator : ImmutableList.of("=", ">", ">=", "<", "<=")) {
+      QueryChanges queryChanges = queryChangesProvider.get();
+      queryChanges.addQuery("label:Code-Review" + operator + "10");
+      queryChanges.addQuery("label:Code-Review" + operator + "-10");
+      queryChanges.addQuery("Code-Review" + operator + "10");
+      queryChanges.addQuery("Code-Review" + operator + "-10");
+      assertThat(queryChanges.apply(TopLevelResource.INSTANCE).statusCode()).isEqualTo(SC_OK);
+    }
+  }
+
   private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
     for (ChangeInfo info : results) {
       assertThat(info._moreChanges).isNull();
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
index 0e89de2..ec4a3a3 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RevertIT.java
@@ -21,10 +21,10 @@
 import static java.util.stream.Collectors.toList;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.Permission;
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 70e4f89..e543976 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -40,7 +40,6 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.ProjectResetter;
@@ -48,6 +47,7 @@
 import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
diff --git a/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java b/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
index a120eac..ff873dd 100644
--- a/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/plugin/PluginIT.java
@@ -21,8 +21,8 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.extensions.api.plugins.InstallPluginInput;
diff --git a/javatests/com/google/gerrit/acceptance/api/plugin/PluginLoaderIT.java b/javatests/com/google/gerrit/acceptance/api/plugin/PluginLoaderIT.java
index 7eb3680..744cc2a 100644
--- a/javatests/com/google/gerrit/acceptance/api/plugin/PluginLoaderIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/plugin/PluginLoaderIT.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.acceptance.api.plugin;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.server.plugins.MissingMandatoryPluginsException;
 import org.junit.Test;
 import org.junit.runner.Description;
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
index 1a8790a..78c8209 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
@@ -35,10 +35,10 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.Nullable;
diff --git a/javatests/com/google/gerrit/acceptance/api/project/SetParentIT.java b/javatests/com/google/gerrit/acceptance/api/project/SetParentIT.java
index cf7aab4..1539334 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/SetParentIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/SetParentIT.java
@@ -19,8 +19,8 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.Permission;
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/GetBlameIT.java b/javatests/com/google/gerrit/acceptance/api/revision/GetBlameIT.java
new file mode 100644
index 0000000..8dfebad
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/api/revision/GetBlameIT.java
@@ -0,0 +1,128 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.api.revision;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.extensions.common.BlameInfo;
+import com.google.gerrit.extensions.common.RangeInfo;
+import java.util.List;
+import org.junit.Test;
+
+public class GetBlameIT extends AbstractDaemonTest {
+  @Test
+  public void forNonExistingFile() throws Exception {
+    PushOneCommit.Result r = createChange("Test Change", "foo.txt", "FOO");
+    List<BlameInfo> blameInfos =
+        gApi.changes().id(r.getChangeId()).current().file("non-existing.txt").blameRequest().get();
+
+    // File doesn't exist in commit.
+    assertThat(blameInfos).isEmpty();
+  }
+
+  @Test
+  public void forNonExistingFileFromBase() throws Exception {
+    PushOneCommit.Result r = createChange("Test Change", "foo.txt", "FOO");
+    List<BlameInfo> blameInfos =
+        gApi.changes()
+            .id(r.getChangeId())
+            .current()
+            .file("non-existing.txt")
+            .blameRequest()
+            .forBase(true)
+            .get();
+
+    // File doesn't exist in base commit.
+    assertThat(blameInfos).isEmpty();
+  }
+
+  @Test
+  public void forNewlyAddedFile() throws Exception {
+    PushOneCommit.Result r = createChange("Test Change", "foo.txt", "FOO");
+    List<BlameInfo> blameInfos =
+        gApi.changes().id(r.getChangeId()).current().file("foo.txt").blameRequest().get();
+
+    assertThat(blameInfos).hasSize(1);
+    BlameInfo blameInfo = blameInfos.get(0);
+    assertThat(blameInfo.author).isEqualTo(admin.fullName());
+    assertThat(blameInfo.id).isEqualTo(r.getCommit().getId().name());
+    assertThat(blameInfo.commitMsg).isEqualTo(r.getCommit().getFullMessage());
+    assertThat(blameInfo.time).isEqualTo(r.getCommit().getCommitTime());
+
+    assertThat(blameInfo.ranges).hasSize(1);
+    RangeInfo rangeInfo = blameInfo.ranges.get(0);
+    assertThat(rangeInfo.start).isEqualTo(1);
+    assertThat(rangeInfo.end).isEqualTo(1);
+  }
+
+  @Test
+  public void forNewlyAddedFileFromBase() throws Exception {
+    String changeId = createChange("Test Change", "foo.txt", "FOO").getChangeId();
+    List<BlameInfo> blameInfos =
+        gApi.changes().id(changeId).current().file("foo.txt").blameRequest().forBase(true).get();
+
+    // File doesn't exist in base commit.
+    assertThat(blameInfos).isEmpty();
+  }
+
+  @Test
+  public void forRecreatedFile() throws Exception {
+    // Create change that adds 'foo.txt'.
+    createChange("Change 1", "foo.txt", "FOO");
+
+    // Create change that deletes 'foo.txt'.
+    pushFactory
+        .create(admin.newIdent(), testRepo, "Change 2", "foo.txt", "FOO")
+        .rm("refs/for/master");
+
+    // Create change that recreates 'foo.txt'.
+    PushOneCommit.Result r = createChange("Change 3", "foo.txt", "FOO");
+    List<BlameInfo> blameInfos =
+        gApi.changes().id(r.getChangeId()).current().file("foo.txt").blameRequest().get();
+
+    assertThat(blameInfos).hasSize(1);
+    BlameInfo blameInfo = blameInfos.get(0);
+    assertThat(blameInfo.author).isEqualTo(admin.fullName());
+    assertThat(blameInfo.id).isEqualTo(r.getCommit().getId().name());
+    assertThat(blameInfo.commitMsg).isEqualTo(r.getCommit().getFullMessage());
+    assertThat(blameInfo.time).isEqualTo(r.getCommit().getCommitTime());
+
+    assertThat(blameInfo.ranges).hasSize(1);
+    RangeInfo rangeInfo = blameInfo.ranges.get(0);
+    assertThat(rangeInfo.start).isEqualTo(1);
+    assertThat(rangeInfo.end).isEqualTo(1);
+  }
+
+  @Test
+  public void forRecreatedFileFromBase() throws Exception {
+    // Create change that adds 'foo.txt'.
+    createChange("Change 1", "foo.txt", "FOO");
+
+    // Create change that deletes 'foo.txt'.
+    pushFactory
+        .create(admin.newIdent(), testRepo, "Change 2", "foo.txt", "FOO")
+        .rm("refs/for/master");
+
+    // Create change that recreates 'foo.txt'.
+    String changeId3 = createChange("Change 3", "foo.txt", "FOO").getChangeId();
+    List<BlameInfo> blameInfos =
+        gApi.changes().id(changeId3).current().file("foo.txt").blameRequest().forBase(true).get();
+
+    // File doesn't exist in base commit.
+    assertThat(blameInfos).isEmpty();
+  }
+}
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index ad73e0f..61d0fd5 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -46,6 +46,7 @@
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.TestProjectInput;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.Permission;
@@ -1062,6 +1063,7 @@
   }
 
   @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "true")
   public void mergeable() throws Exception {
     ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();
 
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
index 62a7037..e3b7456 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
@@ -25,8 +25,8 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
 import com.google.gerrit.extensions.client.Comment;
diff --git a/javatests/com/google/gerrit/acceptance/config/BUILD b/javatests/com/google/gerrit/acceptance/config/BUILD
new file mode 100644
index 0000000..350f2e6
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/config/BUILD
@@ -0,0 +1,7 @@
+load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests")
+
+acceptance_tests(
+    srcs = glob(["*.java"]),
+    group = "config",
+    labels = ["config"],
+)
diff --git a/javatests/com/google/gerrit/acceptance/annotation/UseGerritConfigAnnotationTest.java b/javatests/com/google/gerrit/acceptance/config/UseGerritConfigAnnotationTest.java
similarity index 96%
rename from javatests/com/google/gerrit/acceptance/annotation/UseGerritConfigAnnotationTest.java
rename to javatests/com/google/gerrit/acceptance/config/UseGerritConfigAnnotationTest.java
index d5ac2f7..f72aa74 100644
--- a/javatests/com/google/gerrit/acceptance/annotation/UseGerritConfigAnnotationTest.java
+++ b/javatests/com/google/gerrit/acceptance/config/UseGerritConfigAnnotationTest.java
@@ -12,12 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.annotation;
+package com.google.gerrit.acceptance.config;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import org.junit.Test;
 
 public class UseGerritConfigAnnotationTest extends AbstractDaemonTest {
diff --git a/javatests/com/google/gerrit/acceptance/annotation/UseGlobalPluginConfigAnnotationTest.java b/javatests/com/google/gerrit/acceptance/config/UseGlobalPluginConfigAnnotationTest.java
similarity index 96%
rename from javatests/com/google/gerrit/acceptance/annotation/UseGlobalPluginConfigAnnotationTest.java
rename to javatests/com/google/gerrit/acceptance/config/UseGlobalPluginConfigAnnotationTest.java
index 44d9e46..cfad6f2 100644
--- a/javatests/com/google/gerrit/acceptance/annotation/UseGlobalPluginConfigAnnotationTest.java
+++ b/javatests/com/google/gerrit/acceptance/config/UseGlobalPluginConfigAnnotationTest.java
@@ -12,12 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.acceptance.annotation;
+package com.google.gerrit.acceptance.config;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GlobalPluginConfig;
 import com.google.gerrit.acceptance.UseLocalDisk;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index cab12b3..60cf4f1 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -52,13 +52,13 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.SkipProjectClone;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.GlobalCapability;
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index 0ac40a0..d1d197b 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -29,10 +29,10 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.Nullable;
@@ -1446,7 +1446,7 @@
   private TestRefAdvertiser.Result getReceivePackRefs() throws Exception {
     try (Repository repo = repoManager.openRepository(project)) {
       AdvertiseRefsHook adv =
-          ReceiveCommitsAdvertiseRefsHookChain.createForTest(queryProvider, project);
+          ReceiveCommitsAdvertiseRefsHookChain.createForTest(queryProvider, project, admin.id());
       ReceivePack rp = new ReceivePack(repo);
       rp.setAdvertiseRefsHook(adv);
       TestRefAdvertiser advertiser = new TestRefAdvertiser(repo);
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
index 09da628..329723b7 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsIT.java
@@ -18,10 +18,10 @@
 import static com.google.common.truth.TruthJUnit.assume;
 
 import com.google.common.collect.Iterables;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.UseClockStep;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.testing.ConfigSuite;
diff --git a/javatests/com/google/gerrit/acceptance/rest/TraceIT.java b/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
index 52de5ad..d09aad8 100644
--- a/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
@@ -28,9 +28,9 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.events.ChangeIndexedListener;
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
index faaba06..a3c0295 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
@@ -29,11 +29,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.acceptance.RestSession;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.GlobalCapability;
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
index 8e5eaa4..eb125a0 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/AccountsRestApiBindingsIT.java
@@ -21,8 +21,8 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.extensions.common.ChangeInput;
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRemoteAdminRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRemoteAdminRestApiBindingsIT.java
index d60148e..dd6eb7a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRemoteAdminRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/PluginsRemoteAdminRestApiBindingsIT.java
@@ -18,7 +18,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.rest.util.RestApiCallHelper;
 import com.google.gerrit.acceptance.rest.util.RestCall;
 import com.google.gerrit.common.RawInputUtil;
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
index b8ab752..55eeaf4 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ProjectsRestApiBindingsIT.java
@@ -83,7 +83,8 @@
               .expectedResponseCode(SC_NOT_FOUND)
               .build(),
           RestCall.get("/projects/%s/dashboards"),
-          RestCall.put("/projects/%s/labels/new-label"));
+          RestCall.put("/projects/%s/labels/new-label"),
+          RestCall.post("/projects/%s/labels/"));
 
   /**
    * Child project REST endpoints to be tested, each URL contains placeholders for the parent
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
index 6d140c6..5573ad7 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/RootCollectionsRestApiBindingsIT.java
@@ -20,7 +20,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.rest.util.RestCall;
 import org.junit.Test;
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 12fe263..eff98b3 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -44,7 +44,6 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
@@ -52,6 +51,7 @@
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.acceptance.UseClockStep;
 import com.google.gerrit.acceptance.UseTimezone;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.Nullable;
@@ -1205,7 +1205,7 @@
   }
 
   @Test
-  @GerritConfig(name = "index.reindexAfterRefUpdate", value = "true")
+  @GerritConfig(name = "index.change.indexMergeable", value = "true")
   public void submitSchedulesOpenChangesOfSameBranchForReindexing() throws Throwable {
     // Create a merged change.
     PushOneCommit push =
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
index 3030b02..ea3a6a0 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/IndexChangeIT.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
@@ -58,6 +59,7 @@
   }
 
   @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "true")
   public void indexChangeAfterOwnerLosesVisibility() throws Exception {
     // Create a test group with 2 users as members
     TestAccount user2 = accountCreator.user2();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
index 063f1a0..37b1713 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/MoveChangeIT.java
@@ -22,10 +22,10 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.GitUtil;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.LabelFunction;
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java b/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
index 1a3c10f..f5cca1b 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
@@ -18,8 +18,8 @@
 import static com.google.gerrit.testing.GerritJUnit.assertThrows;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.projects.ConfigInput;
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
index 8e0042c..568c63b 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SuggestReviewersIT.java
@@ -27,8 +27,8 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
diff --git a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
index 1d87ca1..996119d 100644
--- a/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/config/ServerInfoIT.java
@@ -18,9 +18,9 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.extensions.api.plugins.InstallPluginInput;
 import com.google.gerrit.extensions.client.AccountFieldName;
diff --git a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
deleted file mode 100644
index e153e561..0000000
--- a/javatests/com/google/gerrit/acceptance/rest/group/GroupsIT.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License
-
-package com.google.gerrit.acceptance.rest.group;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
-import org.junit.Test;
-
-public class GroupsIT extends AbstractDaemonTest {
-  @Test
-  public void invalidQueryOptions() throws Exception {
-    RestResponse r = adminRestSession.put("/groups/?query=foo&query2=bar");
-    r.assertBadRequest();
-    assertThat(r.getEntityContent())
-        .isEqualTo("\"query\" and \"query2\" options are mutually exclusive");
-  }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/group/ListGroupsIT.java b/javatests/com/google/gerrit/acceptance/rest/group/ListGroupsIT.java
new file mode 100644
index 0000000..d8132b7
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/group/ListGroupsIT.java
@@ -0,0 +1,37 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.group;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.extensions.common.GroupInfo;
+import com.google.gson.reflect.TypeToken;
+import java.util.Map;
+import org.junit.Test;
+
+public class ListGroupsIT extends AbstractDaemonTest {
+  @Test
+  public void listAllGroups() throws Exception {
+    RestResponse response = adminRestSession.get("/groups/");
+    response.assertOK();
+
+    Map<String, GroupInfo> groupMap =
+        newGson()
+            .fromJson(response.getReader(), new TypeToken<Map<String, GroupInfo>>() {}.getType());
+    assertThat(groupMap.keySet()).containsExactly("Administrators", "Non-Interactive Users");
+  }
+}
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
index 6b2baa7..0ba4f16 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
@@ -30,9 +30,9 @@
 import com.google.common.collect.Sets;
 import com.google.common.net.HttpHeaders;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.acceptance.UseLocalDisk;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.GlobalCapability;
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index 4f1be30..5636014 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.extensions.api.projects.BranchInput;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.inject.Inject;
@@ -172,6 +173,24 @@
     assertThat(thrown).hasMessageThat().contains("Not allowed to delete group branch.");
   }
 
+  @Test
+  public void cannotDeleteRefsMetaConfig() throws Exception {
+    MethodNotAllowedException thrown =
+        assertThrows(
+            MethodNotAllowedException.class,
+            () -> branch(BranchNameKey.create(allUsers, RefNames.REFS_CONFIG)).delete());
+    assertThat(thrown).hasMessageThat().contains("not allowed to delete branch refs/meta/config");
+  }
+
+  @Test
+  public void cannotDeleteHead() throws Exception {
+    MethodNotAllowedException thrown =
+        assertThrows(
+            MethodNotAllowedException.class,
+            () -> branch(BranchNameKey.create(allUsers, RefNames.HEAD)).delete());
+    assertThat(thrown).hasMessageThat().contains("not allowed to delete HEAD");
+  }
+
   private void blockForcePush() throws Exception {
     projectOperations
         .project(project)
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
index 3cdeafd..ad90109 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.extensions.api.projects.ProjectApi;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.inject.Inject;
 import java.util.HashMap;
@@ -156,6 +157,26 @@
     assertThat(thrown).hasMessageThat().contains("branches must be specified");
   }
 
+  @Test
+  public void cannotDeleteRefsMetaConfig() throws Exception {
+    DeleteBranchesInput input = new DeleteBranchesInput();
+    input.branches = Lists.newArrayList();
+    input.branches.add(RefNames.REFS_CONFIG);
+    MethodNotAllowedException thrown =
+        assertThrows(MethodNotAllowedException.class, () -> project().deleteBranches(input));
+    assertThat(thrown).hasMessageThat().contains("not allowed to delete branch refs/meta/config");
+  }
+
+  @Test
+  public void cannotDeleteHead() throws Exception {
+    DeleteBranchesInput input = new DeleteBranchesInput();
+    input.branches = Lists.newArrayList();
+    input.branches.add(RefNames.HEAD);
+    MethodNotAllowedException thrown =
+        assertThrows(MethodNotAllowedException.class, () -> project().deleteBranches(input));
+    assertThat(thrown).hasMessageThat().contains("not allowed to delete HEAD");
+  }
+
   private String errorMessageForBranches(List<String> branches) {
     StringBuilder message = new StringBuilder();
     for (String branch : branches) {
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
index 29d3eb2..bb08267 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
@@ -26,10 +26,10 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.Sandboxed;
 import com.google.gerrit.acceptance.TestProjectInput;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.common.data.Permission;
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/PostLabelsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/PostLabelsIT.java
new file mode 100644
index 0000000..9e6b051
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/project/PostLabelsIT.java
@@ -0,0 +1,456 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.project;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
+import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
+import com.google.gerrit.common.data.LabelFunction;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.extensions.common.BatchLabelInput;
+import com.google.gerrit.extensions.common.LabelDefinitionInfo;
+import com.google.gerrit.extensions.common.LabelDefinitionInput;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.server.restapi.project.PostLabels;
+import com.google.inject.Inject;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+/** Tests for the {@link PostLabels} REST endpoint. */
+public class PostLabelsIT extends AbstractDaemonTest {
+  @Inject private RequestScopeOperations requestScopeOperations;
+  @Inject private ProjectOperations projectOperations;
+
+  @Test
+  public void anonymous() throws Exception {
+    requestScopeOperations.setApiUserAnonymous();
+    AuthException thrown =
+        assertThrows(
+            AuthException.class,
+            () -> gApi.projects().name(allProjects.get()).labels(new BatchLabelInput()));
+    assertThat(thrown).hasMessageThat().contains("Authentication required");
+  }
+
+  @Test
+  public void notAllowed() throws Exception {
+    projectOperations
+        .project(allProjects)
+        .forUpdate()
+        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(REGISTERED_USERS))
+        .update();
+
+    requestScopeOperations.setApiUser(user.id());
+    AuthException thrown =
+        assertThrows(
+            AuthException.class,
+            () -> gApi.projects().name(allProjects.get()).labels(new BatchLabelInput()));
+    assertThat(thrown).hasMessageThat().contains("write refs/meta/config not permitted");
+  }
+
+  @Test
+  public void deleteNonExistingLabel() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo");
+
+    UnprocessableEntityException thrown =
+        assertThrows(
+            UnprocessableEntityException.class,
+            () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo not found");
+  }
+
+  @Test
+  public void deleteLabels() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+    configLabel("Bar", LabelFunction.NO_OP);
+    assertThat(gApi.projects().name(project.get()).labels().get()).isNotEmpty();
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo", "Bar");
+    gApi.projects().name(project.get()).labels(input);
+    assertThat(gApi.projects().name(project.get()).labels().get()).isEmpty();
+  }
+
+  @Test
+  public void deleteLabels_labelNamesAreTrimmed() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+    configLabel("Bar", LabelFunction.NO_OP);
+    assertThat(gApi.projects().name(project.get()).labels().get()).isNotEmpty();
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of(" Foo ", " Bar ");
+    gApi.projects().name(project.get()).labels(input);
+    assertThat(gApi.projects().name(project.get()).labels().get()).isEmpty();
+  }
+
+  @Test
+  public void cannotDeleteTheSameLabelTwice() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo", "Foo");
+
+    UnprocessableEntityException thrown =
+        assertThrows(
+            UnprocessableEntityException.class,
+            () -> gApi.projects().name(project.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo not found");
+  }
+
+  @Test
+  public void cannotCreateLabelWithNameThatIsAlreadyInUse() throws Exception {
+    LabelDefinitionInput labelInput = new LabelDefinitionInput();
+    labelInput.name = "Code-Review";
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(labelInput);
+
+    ResourceConflictException thrown =
+        assertThrows(
+            ResourceConflictException.class,
+            () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Code-Review already exists");
+  }
+
+  @Test
+  public void cannotCreateTwoLabelsWithTheSameName() throws Exception {
+    LabelDefinitionInput fooInput = new LabelDefinitionInput();
+    fooInput.name = "Foo";
+    fooInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(fooInput, fooInput);
+
+    ResourceConflictException thrown =
+        assertThrows(
+            ResourceConflictException.class,
+            () -> gApi.projects().name(project.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo already exists");
+  }
+
+  @Test
+  public void cannotCreateTwoLabelsWithNamesThatAreTheSameAfterTrim() throws Exception {
+    LabelDefinitionInput foo1Input = new LabelDefinitionInput();
+    foo1Input.name = "Foo";
+    foo1Input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput foo2Input = new LabelDefinitionInput();
+    foo2Input.name = " Foo ";
+    foo2Input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(foo1Input, foo2Input);
+
+    ResourceConflictException thrown =
+        assertThrows(
+            ResourceConflictException.class,
+            () -> gApi.projects().name(project.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo already exists");
+  }
+
+  @Test
+  public void cannotCreateTwoLabelsWithConflictingNames() throws Exception {
+    LabelDefinitionInput foo1Input = new LabelDefinitionInput();
+    foo1Input.name = "Foo";
+    foo1Input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput foo2Input = new LabelDefinitionInput();
+    foo2Input.name = "foo";
+    foo2Input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(foo1Input, foo2Input);
+
+    ResourceConflictException thrown =
+        assertThrows(
+            ResourceConflictException.class,
+            () -> gApi.projects().name(project.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label foo conflicts with existing label Foo");
+  }
+
+  @Test
+  public void createLabels() throws Exception {
+    LabelDefinitionInput fooInput = new LabelDefinitionInput();
+    fooInput.name = "Foo";
+    fooInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput barInput = new LabelDefinitionInput();
+    barInput.name = "Bar";
+    barInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(fooInput, barInput);
+
+    gApi.projects().name(allProjects.get()).labels(input);
+    assertThat(gApi.projects().name(allProjects.get()).label("Foo").get()).isNotNull();
+    assertThat(gApi.projects().name(allProjects.get()).label("Bar").get()).isNotNull();
+  }
+
+  @Test
+  public void createLabels_labelNamesAreTrimmed() throws Exception {
+    LabelDefinitionInput fooInput = new LabelDefinitionInput();
+    fooInput.name = " Foo ";
+    fooInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput barInput = new LabelDefinitionInput();
+    barInput.name = " Bar ";
+    barInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(fooInput, barInput);
+
+    gApi.projects().name(allProjects.get()).labels(input);
+    assertThat(gApi.projects().name(allProjects.get()).label("Foo").get()).isNotNull();
+    assertThat(gApi.projects().name(allProjects.get()).label("Bar").get()).isNotNull();
+  }
+
+  @Test
+  public void cannotCreateLabelWithoutName() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(new LabelDefinitionInput());
+
+    BadRequestException thrown =
+        assertThrows(
+            BadRequestException.class, () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label name is required for new label");
+  }
+
+  @Test
+  public void cannotSetCommitMessageOnLabelDefinitionInputForCreate() throws Exception {
+    LabelDefinitionInput labelInput = new LabelDefinitionInput();
+    labelInput.name = "Foo";
+    labelInput.commitMessage = "Create Label Foo";
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(labelInput);
+
+    BadRequestException thrown =
+        assertThrows(
+            BadRequestException.class, () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown)
+        .hasMessageThat()
+        .contains("commit message on label definition input not supported");
+  }
+
+  @Test
+  public void updateNonExistingLabel() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.update = ImmutableMap.of("Foo", new LabelDefinitionInput());
+
+    UnprocessableEntityException thrown =
+        assertThrows(
+            UnprocessableEntityException.class,
+            () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo not found");
+  }
+
+  @Test
+  public void updateLabels() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+    configLabel("Bar", LabelFunction.NO_OP);
+
+    LabelDefinitionInput fooUpdate = new LabelDefinitionInput();
+    fooUpdate.function = LabelFunction.MAX_WITH_BLOCK.getFunctionName();
+    LabelDefinitionInput barUpdate = new LabelDefinitionInput();
+    barUpdate.name = "Baz";
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.update = ImmutableMap.of("Foo", fooUpdate, "Bar", barUpdate);
+
+    gApi.projects().name(project.get()).labels(input);
+
+    assertThat(gApi.projects().name(project.get()).label("Foo").get().function)
+        .isEqualTo(fooUpdate.function);
+    assertThat(gApi.projects().name(project.get()).label("Baz").get()).isNotNull();
+    assertThrows(
+        ResourceNotFoundException.class,
+        () -> gApi.projects().name(project.get()).label("Bar").get());
+  }
+
+  @Test
+  public void updateLabels_labelNamesAreTrimmed() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+    configLabel("Bar", LabelFunction.NO_OP);
+
+    LabelDefinitionInput fooUpdate = new LabelDefinitionInput();
+    fooUpdate.function = LabelFunction.MAX_WITH_BLOCK.getFunctionName();
+    LabelDefinitionInput barUpdate = new LabelDefinitionInput();
+    barUpdate.name = "Baz";
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.update = ImmutableMap.of(" Foo ", fooUpdate, " Bar ", barUpdate);
+
+    gApi.projects().name(project.get()).labels(input);
+
+    assertThat(gApi.projects().name(project.get()).label("Foo").get().function)
+        .isEqualTo(fooUpdate.function);
+    assertThat(gApi.projects().name(project.get()).label("Baz").get()).isNotNull();
+    assertThrows(
+        ResourceNotFoundException.class,
+        () -> gApi.projects().name(project.get()).label("Bar").get());
+  }
+
+  @Test
+  public void cannotSetCommitMessageOnLabelDefinitionInputForUpdate() throws Exception {
+    LabelDefinitionInput labelInput = new LabelDefinitionInput();
+    labelInput.commitMessage = "Update label";
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.update = ImmutableMap.of("Code-Review", labelInput);
+
+    BadRequestException thrown =
+        assertThrows(
+            BadRequestException.class, () -> gApi.projects().name(allProjects.get()).labels(input));
+    assertThat(thrown)
+        .hasMessageThat()
+        .contains("commit message on label definition input not supported");
+  }
+
+  @Test
+  public void deleteAndRecreateLabel() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+
+    LabelDefinitionInput fooInput = new LabelDefinitionInput();
+    fooInput.name = "Foo";
+    fooInput.function = LabelFunction.MAX_NO_BLOCK.getFunctionName();
+    fooInput.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo");
+    input.create = ImmutableList.of(fooInput);
+
+    gApi.projects().name(project.get()).labels(input);
+
+    LabelDefinitionInfo fooLabel = gApi.projects().name(project.get()).label("Foo").get();
+    assertThat(fooLabel.function).isEqualTo(fooInput.function);
+  }
+
+  @Test
+  public void deleteRecreateAndUpdateLabel() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+
+    LabelDefinitionInput fooCreateInput = new LabelDefinitionInput();
+    fooCreateInput.name = "Foo";
+    fooCreateInput.function = LabelFunction.MAX_NO_BLOCK.getFunctionName();
+    fooCreateInput.values =
+        ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput fooUpdateInput = new LabelDefinitionInput();
+    fooUpdateInput.function = LabelFunction.ANY_WITH_BLOCK.getFunctionName();
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo");
+    input.create = ImmutableList.of(fooCreateInput);
+    input.update = ImmutableMap.of("Foo", fooUpdateInput);
+
+    gApi.projects().name(project.get()).labels(input);
+
+    LabelDefinitionInfo fooLabel = gApi.projects().name(project.get()).label("Foo").get();
+    assertThat(fooLabel.function).isEqualTo(fooUpdateInput.function);
+  }
+
+  @Test
+  public void cannotDeleteAndUpdateLabel() throws Exception {
+    configLabel("Foo", LabelFunction.NO_OP);
+
+    LabelDefinitionInput fooInput = new LabelDefinitionInput();
+    fooInput.function = LabelFunction.MAX_NO_BLOCK.getFunctionName();
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Foo");
+    input.update = ImmutableMap.of("Foo", fooInput);
+
+    UnprocessableEntityException thrown =
+        assertThrows(
+            UnprocessableEntityException.class,
+            () -> gApi.projects().name(project.get()).labels(input));
+    assertThat(thrown).hasMessageThat().contains("label Foo not found");
+  }
+
+  @Test
+  public void createAndUpdateLabel() throws Exception {
+    LabelDefinitionInput fooCreateInput = new LabelDefinitionInput();
+    fooCreateInput.name = "Foo";
+    fooCreateInput.function = LabelFunction.MAX_NO_BLOCK.getFunctionName();
+    fooCreateInput.values =
+        ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
+
+    LabelDefinitionInput fooUpdateInput = new LabelDefinitionInput();
+    fooUpdateInput.function = LabelFunction.ANY_WITH_BLOCK.getFunctionName();
+
+    BatchLabelInput input = new BatchLabelInput();
+    input.create = ImmutableList.of(fooCreateInput);
+    input.update = ImmutableMap.of("Foo", fooUpdateInput);
+
+    gApi.projects().name(project.get()).labels(input);
+
+    LabelDefinitionInfo fooLabel = gApi.projects().name(project.get()).label("Foo").get();
+    assertThat(fooLabel.function).isEqualTo(fooUpdateInput.function);
+  }
+
+  @Test
+  public void noOpUpdate() throws Exception {
+    RevCommit refsMetaConfigHead =
+        projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG);
+
+    gApi.projects().name(allProjects.get()).labels(new BatchLabelInput());
+
+    assertThat(projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG))
+        .isEqualTo(refsMetaConfigHead);
+  }
+
+  @Test
+  public void defaultCommitMessage() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.delete = ImmutableList.of("Code-Review");
+    gApi.projects().name(allProjects.get()).labels(input);
+    assertThat(
+            projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage())
+        .isEqualTo("Update labels");
+  }
+
+  @Test
+  public void withCommitMessage() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.commitMessage = "Batch Update Labels";
+    input.delete = ImmutableList.of("Code-Review");
+    gApi.projects().name(allProjects.get()).labels(input);
+    assertThat(
+            projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage())
+        .isEqualTo(input.commitMessage);
+  }
+
+  @Test
+  public void commitMessageIsTrimmed() throws Exception {
+    BatchLabelInput input = new BatchLabelInput();
+    input.commitMessage = " Batch Update Labels ";
+    input.delete = ImmutableList.of("Code-Review");
+    gApi.projects().name(allProjects.get()).labels(input);
+    assertThat(
+            projectOperations.project(allProjects).getHead(RefNames.REFS_CONFIG).getShortMessage())
+        .isEqualTo("Batch Update Labels");
+  }
+}
diff --git a/javatests/com/google/gerrit/acceptance/server/change/BUILD b/javatests/com/google/gerrit/acceptance/server/change/BUILD
index 4d1634d..500ab06 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/BUILD
+++ b/javatests/com/google/gerrit/acceptance/server/change/BUILD
@@ -4,5 +4,8 @@
     srcs = glob(["*IT.java"]),
     group = "server_change",
     labels = ["server"],
-    deps = ["//java/com/google/gerrit/server/util/time"],
+    deps = [
+        "//java/com/google/gerrit/server/logging",
+        "//java/com/google/gerrit/server/util/time",
+    ],
 )
diff --git a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
index d85a07b..65f8aa0 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -29,9 +29,11 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.Patch;
+import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.api.changes.DeleteCommentInput;
 import com.google.gerrit.extensions.api.changes.DraftInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -59,7 +61,6 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -69,6 +70,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.notes.NoteMap;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -82,6 +84,7 @@
   @Inject private Provider<ChangesCollection> changes;
   @Inject private Provider<PostReview> postReview;
   @Inject private RequestScopeOperations requestScopeOperations;
+  @Inject ProjectOperations projectOperations;
 
   private final Integer[] lines = {0, 1};
 
@@ -315,6 +318,47 @@
   }
 
   @Test
+  public void postCommentsUnreachableData() throws Exception {
+    requestScopeOperations.setApiUser(admin.id());
+
+    String file = "file";
+    PushOneCommit push =
+        pushFactory.create(admin.newIdent(), testRepo, "first subject", file, "l1\nl2\n");
+
+    String dest = "refs/for/master";
+    PushOneCommit.Result r1 = push.to(dest);
+    r1.assertOkStatus();
+    String changeId = r1.getChangeId();
+    String revId = r1.getCommit().getName();
+
+    PushOneCommit.Result r2 = amendChange(r1.getChangeId());
+    r2.assertOkStatus();
+
+    String draftRefName = RefNames.refsDraftComments(r1.getChange().getId(), admin.id());
+
+    DraftInput draft = newDraft(file, Side.REVISION, 1, "comment");
+    addDraft(changeId, "1", draft);
+    ReviewInput reviewInput = new ReviewInput();
+    reviewInput.drafts = DraftHandling.PUBLISH;
+    reviewInput.message = "foo";
+    gApi.changes().id(r1.getChangeId()).revision(1).review(reviewInput);
+
+    addDraft(changeId, "2", newDraft(file, Side.REVISION, 2, "comment2"));
+    reviewInput = new ReviewInput();
+    reviewInput.drafts = DraftHandling.PUBLISH_ALL_REVISIONS;
+    reviewInput.message = "bar";
+    gApi.changes().id(r1.getChangeId()).revision(2).review(reviewInput);
+
+    Map<String, List<CommentInfo>> drafts = getDraftComments(changeId, revId);
+    assertThat(drafts.isEmpty()).isTrue();
+
+    try (Repository repo = repoManager.openRepository(allUsers)) {
+      Ref ref = repo.exactRef(draftRefName);
+      assertThat(ref).isNull();
+    }
+  }
+
+  @Test
   public void listComments() throws Exception {
     String file = "file";
     PushOneCommit push =
@@ -1002,20 +1046,6 @@
     assertThat(getChangeSortedComments(id.get())).hasSize(3);
   }
 
-  @Test
-  public void jsonCommentHasLegacyFormatFalse() throws Exception {
-    PushOneCommit.Result result = createChange();
-    Change.Id changeId = result.getChange().getId();
-    addComment(result.getChangeId(), "comment");
-
-    Collection<com.google.gerrit.entities.Comment> comments =
-        notesFactory.createChecked(project, changeId).getComments().values();
-    assertThat(comments).hasSize(1);
-    com.google.gerrit.entities.Comment comment = comments.iterator().next();
-    assertThat(comment.message).isEqualTo("comment");
-    assertThat(comment.legacyFormat).isFalse();
-  }
-
   private List<CommentInfo> getRevisionComments(String changeId, String revId) throws Exception {
     return getPublishedComments(changeId, revId).values().stream()
         .flatMap(List::stream)
diff --git a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
index 1e2d1ba..08719d3 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
@@ -39,6 +39,7 @@
 import com.google.gerrit.server.change.ConsistencyChecker;
 import com.google.gerrit.server.change.NotifyResolver;
 import com.google.gerrit.server.change.PatchSetInserter;
+import com.google.gerrit.server.logging.RequestId;
 import com.google.gerrit.server.notedb.ChangeNoteUtil;
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.notedb.Sequences;
@@ -313,7 +314,8 @@
             @Override
             public boolean updateChange(ChangeContext ctx) {
               ctx.getChange().setStatus(Change.Status.MERGED);
-              ctx.getUpdate(ctx.getChange().currentPatchSetId()).fixStatus(Change.Status.MERGED);
+              ctx.getUpdate(ctx.getChange().currentPatchSetId())
+                  .fixStatusToMerged(new RequestId(ctx.getChange().getId().toString()));
               return true;
             }
           });
@@ -862,7 +864,8 @@
             @Override
             public boolean updateChange(ChangeContext ctx) {
               ctx.getChange().setStatus(Change.Status.MERGED);
-              ctx.getUpdate(ctx.getChange().currentPatchSetId()).fixStatus(Change.Status.MERGED);
+              ctx.getUpdate(ctx.getChange().currentPatchSetId())
+                  .fixStatusToMerged(new RequestId(ctx.getChange().getId().toString()));
               return true;
             }
           });
diff --git a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index e369d1b..b544f6e 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -25,11 +25,11 @@
 import com.google.common.collect.Iterables;
 import com.google.common.truth.Correspondence;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.UseClockStep;
 import com.google.gerrit.acceptance.UseTimezone;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
diff --git a/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java b/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
index 7c78d61..b23f9a3 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
@@ -39,7 +39,9 @@
 import com.google.gerrit.server.patch.Text;
 import com.google.inject.Inject;
 import com.google.inject.name.Named;
+import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
@@ -66,6 +68,25 @@
   private Cache<PatchListKey, PatchList> abstractPatchListCache;
 
   @Test
+  public void ensureLegacyBackendIsUsedForFileCacheBackend() throws Exception {
+    Field fileCacheField = patchListCache.getClass().getDeclaredField("fileCache");
+    fileCacheField.setAccessible(true);
+    // Use the reflection to access "localCache" field that is only present in Guava backend.
+    assertThat(
+            Arrays.stream(fileCacheField.get(patchListCache).getClass().getDeclaredFields())
+                .anyMatch(f -> f.getName().equals("localCache")))
+        .isTrue();
+
+    // intraCache (and all other cache backends) should use Caffeine backend.
+    Field intraCacheField = patchListCache.getClass().getDeclaredField("intraCache");
+    intraCacheField.setAccessible(true);
+    assertThat(
+            Arrays.stream(intraCacheField.get(patchListCache).getClass().getDeclaredFields())
+                .noneMatch(f -> f.getName().equals("localCache")))
+        .isTrue();
+  }
+
+  @Test
   public void listPatchesAgainstBase() throws Exception {
     commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();
     pushHead(testRepo, "refs/heads/master", false);
diff --git a/javatests/com/google/gerrit/acceptance/server/event/EventPayloadIT.java b/javatests/com/google/gerrit/acceptance/server/event/EventPayloadIT.java
index 8744cfad..d973934 100644
--- a/javatests/com/google/gerrit/acceptance/server/event/EventPayloadIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/event/EventPayloadIT.java
@@ -19,8 +19,8 @@
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.extensions.events.RevisionCreatedListener;
 import com.google.inject.Inject;
 import org.junit.Test;
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
index d0b7f15d..cc61dfb 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/EmailValidatorIT.java
@@ -19,7 +19,7 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.server.mail.send.OutgoingEmailValidator;
 import com.google.inject.Inject;
 import java.io.BufferedReader;
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java b/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
index 13f0416..e03f6fe 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
@@ -16,8 +16,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
 import com.google.gerrit.extensions.common.CommentInfo;
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
index c395c81..0ae9ad2 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
@@ -16,7 +16,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import com.google.gerrit.acceptance.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.mail.EmailHeader;
 import java.net.URI;
 import java.util.Map;
diff --git a/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java b/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
index 4fe0df4..f866fff 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
@@ -22,10 +22,10 @@
 import com.google.gerrit.acceptance.ChangeIndexedCounter;
 import com.google.gerrit.acceptance.ExtensionRegistry;
 import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.inject.Inject;
diff --git a/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java b/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
index 34406e0..f1db016 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
@@ -19,11 +19,11 @@
 
 import com.google.common.base.Splitter;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.PushOneCommit.Result;
 import com.google.gerrit.acceptance.UseSsh;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.git.ObjectIds;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
diff --git a/javatests/com/google/gerrit/index/query/RangeUtilTest.java b/javatests/com/google/gerrit/index/query/RangeUtilTest.java
new file mode 100644
index 0000000..681f9d99b
--- /dev/null
+++ b/javatests/com/google/gerrit/index/query/RangeUtilTest.java
@@ -0,0 +1,34 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.index.query;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.index.query.RangeUtil.Range;
+import org.junit.Test;
+
+public class RangeUtilTest {
+  @Test
+  public void getRangeForValueOutsideOfMinMaxRange_minNotGreaterThanMax() {
+    for (String operator : ImmutableList.of("=", ">", ">=", "<", "<=")) {
+      Range range = RangeUtil.getRange("foo", operator, 10, -4, 4);
+      assertThat(range.min).isAtMost(range.max);
+
+      range = RangeUtil.getRange("foo", operator, -10, -4, 4);
+      assertThat(range.min).isAtMost(range.max);
+    }
+  }
+}
diff --git a/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java b/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
index 9a48a68..3dfbefe 100644
--- a/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
+++ b/javatests/com/google/gerrit/server/index/change/FakeQueryBuilder.java
@@ -18,6 +18,7 @@
 import com.google.gerrit.index.query.Predicate;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
+import org.eclipse.jgit.lib.Config;
 import org.junit.Ignore;
 
 @Ignore
@@ -26,8 +27,34 @@
     super(
         new ChangeQueryBuilder.Definition<>(FakeQueryBuilder.class),
         new ChangeQueryBuilder.Arguments(
-            null, null, null, null, null, null, null, null, null, null, null, null, null, null,
-            null, null, null, null, indexes, null, null, null, null, null, null, null, null));
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            indexes,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            null,
+            new Config()));
   }
 
   @Operator
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 0d7f2bd..6ece894 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -938,7 +938,6 @@
                 .put("revId", String.class)
                 .put("serverId", String.class)
                 .put("unresolved", boolean.class)
-                .put("legacyFormat", boolean.class)
                 .build());
   }
 
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 2c5fcc4..56b3aea 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -30,6 +30,7 @@
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.SECONDS;
 import static java.util.stream.Collectors.toList;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.fail;
 
 import com.google.common.base.MoreObjects;
@@ -41,6 +42,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Streams;
 import com.google.common.truth.ThrowableSubject;
+import com.google.gerrit.acceptance.config.GerritConfig;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.data.LabelType;
@@ -79,6 +81,7 @@
 import com.google.gerrit.index.IndexConfig;
 import com.google.gerrit.index.Schema;
 import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryParseException;
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.CurrentUser;
@@ -2023,6 +2026,7 @@
   }
 
   @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "true")
   public void mergeable() throws Exception {
     TestRepository<Repo> repo = createProject("repo");
     RevCommit commit1 = repo.parseBody(repo.commit().add("file1", "contents1").create());
@@ -2040,7 +2044,7 @@
     // If a change gets submitted, the remaining open changes get reindexed asynchronously to update
     // their mergeability information. If the further assertions in this test are done before the
     // asynchronous reindex completed they fail because the mergeability information in the index
-    // was not updated yet. To avoid this flakiness reindexAfterRefUpdate is switched off for the
+    // was not updated yet. To avoid this flakiness indexMergeable is switched off for the
     // tests and we index change2 synchronously here.
     gApi.changes().id(change2.getChangeId()).index();
 
@@ -2502,6 +2506,19 @@
     assertQueryByIds("revertof:" + changeToRevert._number, Change.id(changeThatReverts._number));
   }
 
+  @Test
+  public void submissionId() throws Exception {
+    TestRepository<Repo> repo = createProject("repo");
+    Change change = insert(repo, newChange(repo));
+    // create irrelevant change
+    insert(repo, newChange(repo));
+    gApi.changes().id(change.getChangeId()).current().review(ReviewInput.approve());
+    gApi.changes().id(change.getChangeId()).current().submit();
+    String submissionId = gApi.changes().id(change.getChangeId()).get().submissionId;
+
+    assertQueryByIds("submissionid:" + submissionId, change.getId());
+  }
+
   /** Change builder for helping in tests for dashboard sections. */
   protected class DashboardChangeState {
     private final Account.Id ownerId;
@@ -3066,6 +3083,20 @@
     }
   }
 
+  @Test
+  @GerritConfig(name = "index.change.indexMergeable", value = "false")
+  public void mergeableFailsWhenNotIndexed() throws Exception {
+    TestRepository<Repo> repo = createProject("repo");
+    RevCommit commit1 = repo.parseBody(repo.commit().add("file1", "contents1").create());
+    insert(repo, newChangeForCommit(repo, commit1));
+
+    Throwable thrown = assertThrows(Throwable.class, () -> assertQuery("status:open is:mergeable"));
+    assertThat(thrown.getCause()).isInstanceOf(QueryParseException.class);
+    assertThat(thrown)
+        .hasMessageThat()
+        .contains("server does not support 'mergeable'. check configs");
+  }
+
   protected ChangeInserter newChange(TestRepository<Repo> repo) throws Exception {
     return newChange(repo, null, null, null, null, false);
   }
diff --git a/javatests/com/google/gerrit/server/query/change/BUILD b/javatests/com/google/gerrit/server/query/change/BUILD
index d0162d3..e5b51e7 100644
--- a/javatests/com/google/gerrit/server/query/change/BUILD
+++ b/javatests/com/google/gerrit/server/query/change/BUILD
@@ -16,12 +16,14 @@
         "//prolog:gerrit-prolog-common",
     ],
     deps = [
+        "//java/com/google/gerrit/acceptance/config",
         "//java/com/google/gerrit/acceptance/testsuite/project",
         "//java/com/google/gerrit/common:annotations",
         "//java/com/google/gerrit/common:server",
         "//java/com/google/gerrit/entities",
         "//java/com/google/gerrit/extensions:api",
         "//java/com/google/gerrit/index",
+        "//java/com/google/gerrit/index:query_exception",
         "//java/com/google/gerrit/lifecycle",
         "//java/com/google/gerrit/server",
         "//java/com/google/gerrit/server/project/testing:project-test-util",
diff --git a/lib/BUILD b/lib/BUILD
index 13580b1..39c622a 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -1,4 +1,4 @@
-load("@rules_java//java:defs.bzl", "java_library")
+load("@rules_java//java:defs.bzl", "java_import", "java_library")
 
 exports_files(glob([
     "LICENSE-*",
@@ -111,6 +111,29 @@
 )
 
 java_library(
+    name = "caffeine",
+    data = ["//lib:LICENSE-Apache2.0"],
+    visibility = [
+        "//java/com/google/gerrit/server/cache/mem:__pkg__",
+    ],
+    exports = ["@caffeine//jar"],
+)
+
+java_import(
+    name = "caffeine-guava-renamed",
+    jars = ["@caffeine-guava-renamed//file"],
+)
+
+java_library(
+    name = "caffeine-guava",
+    data = ["//lib:LICENSE-Apache2.0"],
+    visibility = [
+        "//java/com/google/gerrit/server/cache/mem:__pkg__",
+    ],
+    exports = [":caffeine-guava-renamed"],
+)
+
+java_library(
     name = "jsch",
     data = ["//lib:LICENSE-jsch"],
     visibility = ["//visibility:public"],
diff --git a/lib/highlightjs/highlight.min.js b/lib/highlightjs/highlight.min.js
index f5e08a1..f1746c3 100644
--- a/lib/highlightjs/highlight.min.js
+++ b/lib/highlightjs/highlight.min.js
@@ -8,8 +8,8 @@
 $jscomp.iteratorFromArray=function(b,h){$jscomp.initSymbolIterator();b instanceof String&&(b+="");var l=0,q={next:function(){if(l<b.length){var u=l++;return{value:h(u,b[u]),done:!1}}q.next=function(){return{done:!0,value:void 0}};return q.next()}};q[Symbol.iterator]=function(){return q};return q};
 $jscomp.polyfill=function(b,h,l,q){if(h){l=$jscomp.global;b=b.split(".");for(q=0;q<b.length-1;q++){var u=b[q];u in l||(l[u]={});l=l[u]}b=b[b.length-1];q=l[b];h=h(q);h!=q&&null!=h&&$jscomp.defineProperty(l,b,{configurable:!0,writable:!0,value:h})}};$jscomp.polyfill("Array.prototype.keys",function(b){return b?b:function(){return $jscomp.iteratorFromArray(this,function(b){return b})}},"es6","es3");
 (function(b){var h="object"===typeof window&&window||"object"===typeof self&&self;"undefined"===typeof exports||exports.nodeType?h&&(h.hljs=b({}),"function"===typeof define&&define.amd&&define([],function(){return h.hljs})):b(exports)})(function(b){function h(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function l(a){var f,c={},b=Array.prototype.slice.call(arguments,1);for(f in a)c[f]=a[f];b.forEach(function(a){for(f in a)c[f]=a[f]});return c}function q(a){var f=[];
-(function g(a,b){for(a=a.firstChild;a;a=a.nextSibling)3===a.nodeType?b+=a.nodeValue.length:1===a.nodeType&&(f.push({event:"start",offset:b,node:a}),b=g(a,b),a.nodeName.toLowerCase().match(/br|hr|img|input/)||f.push({event:"stop",offset:b,node:a}));return b})(a,0);return f}function u(a,f,b){function c(){return a.length&&f.length?a[0].offset!==f[0].offset?a[0].offset<f[0].offset?a:f:"start"===f[0].event?a:f:a.length?a:f}function e(a){r+="<"+a.nodeName.toLowerCase()+H.map.call(a.attributes,function(a){return" "+
-a.nodeName+'="'+h(a.value).replace(/"/g,"&quot;")+'"'}).join("")+">"}function g(a){r+="</"+a.nodeName.toLowerCase()+">"}function k(a){("start"===a.event?e:g)(a.node)}for(var p=0,r="",x=[];a.length||f.length;){var m=c();r+=h(b.substring(p,m[0].offset));p=m[0].offset;if(m===a){x.reverse().forEach(g);do k(m.splice(0,1)[0]),m=c();while(m===a&&m.length&&m[0].offset===p);x.reverse().forEach(e)}else"start"===m[0].event?x.push(m[0].node):x.pop(),k(m.splice(0,1)[0])}return r+h(b.substr(p))}function I(a){return a?
+(function g(a,b){for(a=a.firstChild;a;a=a.nextSibling)3===a.nodeType?b+=a.nodeValue.length:1===a.nodeType&&(f.push({event:"start",offset:b,node:a}),b=g(a,b),a.nodeName.toLowerCase().match(/br|hr|img|input/)||f.push({event:"stop",offset:b,node:a}));return b})(a,0);return f}function u(a,f,c){function b(){return a.length&&f.length?a[0].offset!==f[0].offset?a[0].offset<f[0].offset?a:f:"start"===f[0].event?a:f:a.length?a:f}function e(a){r+="<"+a.nodeName.toLowerCase()+H.map.call(a.attributes,function(a){return" "+
+a.nodeName+'="'+h(a.value).replace(/"/g,"&quot;")+'"'}).join("")+">"}function g(a){r+="</"+a.nodeName.toLowerCase()+">"}function k(a){("start"===a.event?e:g)(a.node)}for(var p=0,r="",x=[];a.length||f.length;){var m=b();r+=h(c.substring(p,m[0].offset));p=m[0].offset;if(m===a){x.reverse().forEach(g);do k(m.splice(0,1)[0]),m=b();while(m===a&&m.length&&m[0].offset===p);x.reverse().forEach(e)}else"start"===m[0].event?x.push(m[0].node):x.pop(),k(m.splice(0,1)[0])}return r+h(c.substr(p))}function I(a){return a?
 a.endsWithParent||I(a.starts):!1}function O(a){a.variants&&!a.cached_variants&&(a.cached_variants=a.variants.map(function(f){return l(a,{variants:null},f)}));return a.cached_variants?a.cached_variants:I(a)?[l(a,{starts:a.starts?l(a.starts):null})]:[a]}function J(a){if(y&&!a.langApiRestored){a.langApiRestored=!0;for(var f in y)a[f]&&(a[y[f]]=a[f]);(a.contains||[]).concat(a.variants||[]).forEach(J)}}function P(a,f){function b(a,b){f&&(b=b.toLowerCase());b.split(" ").forEach(function(f){var b=f.split("|");
 f=b[0];var c=b[1];b=c?Number(c):-1!=Q.indexOf(b[0].toLowerCase())?0:1;d[f]=[a,b]})}var d={};"string"===typeof a?b("keyword",a):D(a).forEach(function(f){b(f,a[f])});return d}function R(a){function f(a){return a&&a.source||a}function b(b,c){return new RegExp(f(b),"m"+(a.case_insensitive?"i":"")+(c?"g":""))}function d(a,b){for(var c=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,d=0,e="",k=0;k<a.length;k++){var g=d+=1,p=f(a[k]);0<k&&(e+=b);for(e+="(";0<p.length;){var h=c.exec(p);if(null==h){e+=p;break}e+=
 p.substring(0,h.index);p=p.substring(h.index+h[0].length);"\\"==h[0][0]&&h[1]?e+="\\"+String(Number(h[1])+g):(e+=h[0],"("==h[0]&&d++)}e+=")"}return e}function e(a){function f(a,f){c[h]=a;k.push([a,f]);h+=(new RegExp(f.toString()+"|")).exec("").length-1+1}for(var c={},e,k=[],g={},h=1,l,t=0;t<a.contains.length;t++)l=a.contains[t],f(l,l.beginKeywords?"\\.?(?:"+l.begin+")\\.?":l.begin);a.terminator_end&&f("end",a.terminator_end);a.illegal&&f("illegal",a.illegal);l=k.map(function(a){return a[1]});e=b(d(l,
@@ -17,8 +17,8 @@
 (c.begin="\\b("+c.beginKeywords.split(" ").join("|")+")\\b"),c.begin||(c.begin=/\B|\b/),c.beginRe=b(c.begin),c.endSameAsBegin&&(c.end=c.begin),c.end||c.endsWithParent||(c.end=/\B|\b/),c.end&&(c.endRe=b(c.end)),c.terminator_end=f(c.end)||"",c.endsWithParent&&d.terminator_end&&(c.terminator_end+=(c.end?"|":"")+d.terminator_end)),c.illegal&&(c.illegalRe=b(c.illegal)),null==c.relevance&&(c.relevance=1),c.contains||(c.contains=[]),c.contains=Array.prototype.concat.apply([],c.contains.map(function(a){return O("self"===
 a?c:a)})),c.contains.forEach(function(a){g(a,c)}),c.starts&&g(c.starts,d),c.terminators=e(c))}g(a)}function B(a,f,c,b){function d(a,f){var c=a.endRe;if((c=c&&c.exec(f))&&0===c.index){for(;a.endsParent&&a.parent;)a=a.parent;return a}if(a.endsWithParent)return d(a.parent,f)}function g(a,f,c,b){return c||""!==f?a?'<span class="'+(b?"":w.classPrefix)+(a+'">')+f+(c?"":"</span>"):f:""}function k(){var a=q,f;if(null!=n.subLanguage)if((f="string"===typeof n.subLanguage)&&!z[n.subLanguage])f=h(t);else{var c=
 f?B(n.subLanguage,t,!0,l[n.subLanguage]):F(t,n.subLanguage.length?n.subLanguage:void 0);0<n.relevance&&(u+=c.relevance);f&&(l[n.subLanguage]=c.top);f=g(c.language,c.value,!1,!0)}else if(n.keywords){c="";var b=0;n.lexemesRe.lastIndex=0;for(f=n.lexemesRe.exec(t);f;){c+=h(t.substring(b,f.index));b=n;var d=f;d=m.case_insensitive?d[0].toLowerCase():d[0];(b=b.keywords.hasOwnProperty(d)&&b.keywords[d])?(u+=b[1],c+=g(b[0],h(f[0]))):c+=h(f[0]);b=n.lexemesRe.lastIndex;f=n.lexemesRe.exec(t)}f=c+h(t.substr(b))}else f=
-h(t);q=a+f;t=""}function p(a){q+=a.className?g(a.className,"",!0):"";n=Object.create(a,{parent:{value:n}})}function r(a,b){var e=b&&b[0];t+=a;if(null==e)return k(),0;if("begin"==x.type&&"end"==b.type&&x.index==b.index&&""===e)return t+=f.slice(b.index,b.index+1),1;x=b;if("begin"===b.type)return e=b[0],(a=b.rule)&&a.endSameAsBegin&&(a.endRe=new RegExp(e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),a.skip?t+=e:(a.excludeBegin&&(t+=e),k(),a.returnBegin||a.excludeBegin||(t=e)),p(a,e),a.returnBegin?
-0:e.length;if("illegal"===b.type&&!c)throw Error('Illegal lexeme "'+e+'" for mode "'+(n.className||"<unnamed>")+'"');if("end"===b.type){a=b[0];b=f.substr(b.index);if(b=d(n,b)){var g=n;g.skip?t+=a:(g.returnEnd||g.excludeEnd||(t+=a),k(),g.excludeEnd&&(t=a));do n.className&&(q+="</span>"),n.skip||n.subLanguage||(u+=n.relevance),n=n.parent;while(n!==b.parent);b.starts&&(b.endSameAsBegin&&(b.starts.endRe=b.endRe),p(b.starts,""));a=g.returnEnd?0:a.length}else a=void 0;if(void 0!=a)return a}t+=e;return e.length}
+h(t);q=a+f;t=""}function p(a){q+=a.className?g(a.className,"",!0):"";n=Object.create(a,{parent:{value:n}})}function r(a,b){var e=b&&b[0];t+=a;if(null==e)return k(),0;if("begin"==x.type&&"end"==b.type&&x.index==b.index&&""===e)return t+=f.slice(b.index,b.index+1),1;x=b;if("begin"===b.type)return e=b[0],(a=b.rule)&&a.endSameAsBegin&&(a.endRe=new RegExp(e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),a.skip?t+=e:(a.excludeBegin&&(t+=e),k(),a.returnBegin||a.excludeBegin||(t=e)),p(a),a.returnBegin?0:
+e.length;if("illegal"===b.type&&!c)throw Error('Illegal lexeme "'+e+'" for mode "'+(n.className||"<unnamed>")+'"');if("end"===b.type){a=b[0];b=f.substr(b.index);if(b=d(n,b)){var g=n;g.skip?t+=a:(g.returnEnd||g.excludeEnd||(t+=a),k(),g.excludeEnd&&(t=a));do n.className&&(q+="</span>"),n.skip||n.subLanguage||(u+=n.relevance),n=n.parent;while(n!==b.parent);b.starts&&(b.endSameAsBegin&&(b.starts.endRe=b.endRe),p(b.starts));a=g.returnEnd?0:a.length}else a=void 0;if(void 0!=a)return a}t+=e;return e.length}
 var x={},m=A(a);if(!m)throw console.error("Could not find the language '{}', did you forget to load/include a language module?".replace("{}",a)),Error('Unknown language: "'+a+'"');R(m);var n=b||m,l={},q="";for(b=n;b!==m;b=b.parent)b.className&&(q=g(b.className,"",!0)+q);var t="",u=0;try{for(var v,y,C=0;;){n.terminators.lastIndex=C;v=n.terminators.exec(f);if(!v)break;y=r(f.substring(C,v.index),v);C=v.index+y}r(f.substr(C));for(b=n;b.parent;b=b.parent)b.className&&(q+="</span>");return{relevance:u,
 value:q,illegal:!1,language:a,top:n}}catch(E){if(E.message&&-1!==E.message.indexOf("Illegal"))return{illegal:!0,relevance:0,value:h(f)};throw E;}}function F(a,f){f=f||w.languages||D(z);var b={relevance:0,value:h(a)},d=b;f.filter(A).filter(K).forEach(function(f){var c=B(f,a,!1);c.language=f;c.relevance>d.relevance&&(d=c);c.relevance>b.relevance&&(d=b,b=c)});d.language&&(b.second_best=d);return b}function L(a){return w.tabReplace||w.useBR?a.replace(S,function(a,b){return w.useBR&&"\n"===a?"<br>":w.tabReplace?
 b.replace(/\t/g,w.tabReplace):""}):a}function M(a){var f,b;a:{var d=a.className+" ";d+=a.parentNode?a.parentNode.className:"";if(b=T.exec(d))d=A(b[1]),d||(console.warn("Could not find the language '{}', did you forget to load/include a language module?".replace("{}",b[1])),console.warn("Falling back to no-highlight mode for this block.",a)),b=d?b[1]:"no-highlight";else{d=d.split(/\s+/);b=0;for(f=d.length;b<f;b++){var e=d[b];if(N.test(e)||A(e)){b=e;break a}}b=void 0}}if(!N.test(b)){w.useBR?(e=document.createElementNS("http://www.w3.org/1999/xhtml",
@@ -57,7 +57,7 @@
 a.C_BLOCK_COMMENT_MODE,{className:"symbol",begin:"\\$[datastore|feature|layer|map|measure|sourcefeature|sourcelayer|targetfeature|targetlayer|value|view]+"},b,{begin:/[{,]\s*/,relevance:0,contains:[{begin:"[A-Za-z_][0-9A-Za-z_]*\\s*:",returnBegin:!0,relevance:0,contains:[{className:"attr",begin:"[A-Za-z_][0-9A-Za-z_]*",relevance:0}]}]},{begin:"("+a.RE_STARTERS_RE+"|\\b(return)\\b)\\s*",keywords:"return",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|[A-Za-z_][0-9A-Za-z_]*)\\s*=>",
 returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:"[A-Za-z_][0-9A-Za-z_]*"},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:f,contains:d}]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_][0-9A-Za-z_]*"}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:d}],illegal:/\[|%/},{begin:/\$[(.]/}],illegal:/#(?!!)/}});b.registerLanguage("cpp",
 function(a){var f={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},b={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},{begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\((?:.|\n)*?\)\1"/}]},d={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],
-relevance:0},e={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},a.inherit(b,{className:"meta-string"}),{className:"meta-string",begin:/<[^\n>]*>/,end:/$/,illegal:"\\n"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},g=a.IDENT_RE+"\\s*\\(",k={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",
+relevance:0},e={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},a.inherit(b,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},g=a.IDENT_RE+"\\s*\\(",k={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",
 built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",
 literal:"true false nullptr NULL"},p=[f,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,d,b];return{aliases:"c cc h c++ h++ hpp hh hxx cxx".split(" "),keywords:k,illegal:"</",contains:p.concat([e,{begin:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",end:">",keywords:k,contains:["self",f]},{begin:a.IDENT_RE+"::",keywords:k},{variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",
 end:/;/}],keywords:k,contains:p.concat([{begin:/\(/,end:/\)/,keywords:k,contains:p.concat(["self"]),relevance:0}]),relevance:0},{className:"function",begin:"("+a.IDENT_RE+"[\\*&\\s]+)+"+g,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:k,illegal:/[^\w\s\*&]/,contains:[{begin:g,returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:k,relevance:0,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,b,d,f,{begin:/\(/,end:/\)/,keywords:k,relevance:0,contains:["self",
@@ -67,13 +67,13 @@
 built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @"},
 contains:[{className:"keyword",begin:"\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?",
 end:"\\s"},a.COMMENT("[;@]","$",{relevance:0}),a.C_BLOCK_COMMENT_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"'",end:"[^\\\\]'",relevance:0},{className:"title",begin:"\\|",end:"\\|",illegal:"\\n",relevance:0},{className:"number",variants:[{begin:"[#$=]?0x[0-9a-f]+"},{begin:"[#$=]?0b[01]+"},{begin:"[#$=]\\d+"},{begin:"\\b\\d+"}],relevance:0},{className:"symbol",variants:[{begin:"^[a-z_\\.\\$][a-z0-9_\\.\\$]+"},{begin:"^\\s*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{begin:"[=#]\\w+"}],relevance:0}]}});
-b.registerLanguage("xml",function(a){var f={endsWithParent:!0,illegal:/</,relevance:0,contains:[{className:"attr",begin:"[A-Za-z0-9\\._:-]+",relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/[^\s"'=<>`]+/}]}]}]};return{aliases:"html xhtml rss atom xjb xsd xsl plist wsf svg".split(" "),case_insensitive:!0,contains:[{className:"meta",begin:"<!DOCTYPE",end:">",relevance:10,contains:[{begin:"\\[",end:"\\]"}]},a.COMMENT("\x3c!--",
-"--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},a.inherit(a.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]},{className:"tag",begin:"<style(?=\\s|>)",end:">",keywords:{name:"style"},
-contains:[f],starts:{end:"</style>",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:"<script(?=\\s|>)",end:">",keywords:{name:"script"},contains:[f],starts:{end:"\x3c/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"tag",begin:"</?",end:"/?>",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},f]}]}});b.registerLanguage("asciidoc",function(a){return{aliases:["adoc"],contains:[a.COMMENT("^/{4,}\\n","\\n/{4,}$",{relevance:10}),
-a.COMMENT("^//","$",{relevance:0}),{className:"title",begin:"^\\.\\w.*$"},{begin:"^[=\\*]{4,}\\n",end:"\\n^[=\\*]{4,}$",relevance:10},{className:"section",relevance:10,variants:[{begin:"^(={1,5}) .+?( \\1)?$"},{begin:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$"}]},{className:"meta",begin:"^:.+?:",end:"\\s",excludeEnd:!0,relevance:10},{className:"meta",begin:"^\\[.+?\\]$",relevance:0},{className:"quote",begin:"^_{4,}\\n",end:"\\n_{4,}$",relevance:10},{className:"code",begin:"^[\\-\\.]{4,}\\n",end:"\\n[\\-\\.]{4,}$",
-relevance:10},{begin:"^\\+{4,}\\n",end:"\\n\\+{4,}$",contains:[{begin:"<",end:">",subLanguage:"xml",relevance:0}],relevance:10},{className:"bullet",begin:"^(\\*+|\\-+|\\.+|[^\\n]+?::)\\s+"},{className:"symbol",begin:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",relevance:10},{className:"strong",begin:"\\B\\*(?![\\*\\s])",end:"(\\n{2}|\\*)",contains:[{begin:"\\\\*\\w",relevance:0}]},{className:"emphasis",begin:"\\B'(?!['\\s])",end:"(\\n{2}|')",contains:[{begin:"\\\\'\\w",relevance:0}],relevance:0},
-{className:"emphasis",begin:"_(?![_\\s])",end:"(\\n{2}|_)",relevance:0},{className:"string",variants:[{begin:"``.+?''"},{begin:"`.+?'"}]},{className:"code",begin:"(`.+?`|\\+.+?\\+)",relevance:0},{className:"code",begin:"^[ \\t]",end:"$",relevance:0},{begin:"^'{3,}[ \\t]*$",relevance:10},{begin:"(link:)?(http|https|ftp|file|irc|image:?):\\S+\\[.*?\\]",returnBegin:!0,contains:[{begin:"(link|image:?):",relevance:0},{className:"link",begin:"\\w",end:"[^\\[]+",relevance:0},{className:"string",begin:"\\[",
-end:"\\]",excludeBegin:!0,excludeEnd:!0,relevance:0}],relevance:10}]}});b.registerLanguage("aspectj",function(a){return{keywords:"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance",
+b.registerLanguage("xml",function(a){var f={className:"symbol",begin:"&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;"},b={endsWithParent:!0,illegal:/</,relevance:0,contains:[{className:"attr",begin:"[A-Za-z0-9\\._:-]+",relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/,contains:[f]},{begin:/'/,end:/'/,contains:[f]},{begin:/[^\s"'=<>`]+/}]}]}]};return{aliases:"html xhtml rss atom xjb xsd xsl plist wsf svg".split(" "),case_insensitive:!0,contains:[{className:"meta",
+begin:"<!DOCTYPE",end:">",relevance:10,contains:[{begin:"\\[",end:"\\]"}]},a.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},f,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},a.inherit(a.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null,
+className:null,contains:null,skip:!0})]},{className:"tag",begin:"<style(?=\\s|>)",end:">",keywords:{name:"style"},contains:[b],starts:{end:"</style>",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:"<script(?=\\s|>)",end:">",keywords:{name:"script"},contains:[b],starts:{end:"\x3c/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"tag",begin:"</?",end:"/?>",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},b]}]}});b.registerLanguage("asciidoc",
+function(a){return{aliases:["adoc"],contains:[a.COMMENT("^/{4,}\\n","\\n/{4,}$",{relevance:10}),a.COMMENT("^//","$",{relevance:0}),{className:"title",begin:"^\\.\\w.*$"},{begin:"^[=\\*]{4,}\\n",end:"\\n^[=\\*]{4,}$",relevance:10},{className:"section",relevance:10,variants:[{begin:"^(={1,5}) .+?( \\1)?$"},{begin:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$"}]},{className:"meta",begin:"^:.+?:",end:"\\s",excludeEnd:!0,relevance:10},{className:"meta",begin:"^\\[.+?\\]$",relevance:0},{className:"quote",begin:"^_{4,}\\n",
+end:"\\n_{4,}$",relevance:10},{className:"code",begin:"^[\\-\\.]{4,}\\n",end:"\\n[\\-\\.]{4,}$",relevance:10},{begin:"^\\+{4,}\\n",end:"\\n\\+{4,}$",contains:[{begin:"<",end:">",subLanguage:"xml",relevance:0}],relevance:10},{className:"bullet",begin:"^(\\*+|\\-+|\\.+|[^\\n]+?::)\\s+"},{className:"symbol",begin:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",relevance:10},{className:"strong",begin:"\\B\\*(?![\\*\\s])",end:"(\\n{2}|\\*)",contains:[{begin:"\\\\*\\w",relevance:0}]},{className:"emphasis",
+begin:"\\B'(?!['\\s])",end:"(\\n{2}|')",contains:[{begin:"\\\\'\\w",relevance:0}],relevance:0},{className:"emphasis",begin:"_(?![_\\s])",end:"(\\n{2}|_)",relevance:0},{className:"string",variants:[{begin:"``.+?''"},{begin:"`.+?'"}]},{className:"code",begin:"(`.+?`|\\+.+?\\+)",relevance:0},{className:"code",begin:"^[ \\t]",end:"$",relevance:0},{begin:"^'{3,}[ \\t]*$",relevance:10},{begin:"(link:)?(http|https|ftp|file|irc|image:?):\\S+\\[.*?\\]",returnBegin:!0,contains:[{begin:"(link|image:?):",relevance:0},
+{className:"link",begin:"\\w",end:"[^\\[]+",relevance:0},{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0,relevance:0}],relevance:10}]}});b.registerLanguage("aspectj",function(a){return{keywords:"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance",
 illegal:/<\/|#/,contains:[a.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"class",beginKeywords:"aspect",end:/[{;=]/,excludeEnd:!0,illegal:/[:;"\[\]]/,contains:[{beginKeywords:"extends implements pertypewithin perthis pertarget percflowbelow percflow issingleton"},a.UNDERSCORE_TITLE_MODE,{begin:/\([^\)]*/,end:/[)]+/,keywords:"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance get set args call",
 excludeEnd:!1}]},{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,relevance:0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"pointcut after before around throwing returning",end:/[)]/,excludeEnd:!1,illegal:/["\[\]]/,contains:[{begin:a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,contains:[a.UNDERSCORE_TITLE_MODE]}]},{begin:/[:]/,returnBegin:!0,end:/[{;]/,relevance:0,excludeEnd:!1,keywords:"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance",
 illegal:/["\[\]]/,contains:[{begin:a.UNDERSCORE_IDENT_RE+"\\s*\\(",keywords:"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance get set args call",
@@ -115,19 +115,19 @@
 {begin:/&sql\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,subLanguage:"sql"},{begin:/&(js|jscript|javascript)</,end:/>/,excludeBegin:!0,excludeEnd:!0,subLanguage:"javascript"},{begin:/&html<\s*</,end:/>\s*>/,subLanguage:"xml"}]}});b.registerLanguage("crmsh",function(a){return{aliases:["crm","pcmk"],case_insensitive:!0,keywords:{keyword:"params meta operations op rule attributes utilization read write deny defined not_defined in_range date spec in ref reference attribute type xpath version and or lt gt tag lte gte eq ne \\ number string",
 literal:"Master Started Slave Stopped start promote demote stop monitor true false"},contains:[a.HASH_COMMENT_MODE,{beginKeywords:"node",starts:{end:"\\s*([\\w_-]+:)?",starts:{className:"title",end:"\\s*[\\$\\w_][\\w_-]*"}}},{beginKeywords:"primitive rsc_template",starts:{className:"title",end:"\\s*[\\$\\w_][\\w_-]*",starts:{end:"\\s*@?[\\w_][\\w_\\.:-]*"}}},{begin:"\\b(group|clone|ms|master|location|colocation|order|fencing_topology|rsc_ticket|acl_target|acl_group|user|role|tag|xml)\\s+",keywords:"group clone ms master location colocation order fencing_topology rsc_ticket acl_target acl_group user role tag xml",
 starts:{className:"title",end:"[\\$\\w_][\\w_-]*"}},{beginKeywords:"property rsc_defaults op_defaults",starts:{className:"title",end:"\\s*([\\w_-]+:)?"}},a.QUOTE_STRING_MODE,{className:"meta",begin:"(ocf|systemd|service|lsb):[\\w_:-]+",relevance:0},{className:"number",begin:"\\b\\d+(\\.\\d+)?(ms|s|h|m)?",relevance:0},{className:"literal",begin:"[-]?(infinity|inf)",relevance:0},{className:"attr",begin:/([A-Za-z\$_#][\w_-]+)=/,relevance:0},{className:"tag",begin:"</?",end:"/?>",relevance:0}]}});b.registerLanguage("crystal",
-function(a){function f(a,f){a=[{begin:a,end:f}];return a[0].contains=a}var b={keyword:"abstract alias annotation as as? asm begin break case class def do else elsif end ensure enum extend for fun if include instance_sizeof is_a? lib macro module next nil? of out pointerof private protected rescue responds_to? return require select self sizeof struct super then type typeof union uninitialized unless until verbatim when while with yield __DIR__ __END_LINE__ __FILE__ __LINE__",literal:"false nil true"},
+function(a){function f(a,b){a=[{begin:a,end:b}];return a[0].contains=a}var b={keyword:"abstract alias annotation as as? asm begin break case class def do else elsif end ensure enum extend for fun if include instance_sizeof is_a? lib macro module next nil? of out pointerof private protected rescue responds_to? return require select self sizeof struct super then type typeof union uninitialized unless until verbatim when while with yield __DIR__ __END_LINE__ __FILE__ __LINE__",literal:"false nil true"},
 d={className:"subst",begin:"#{",end:"}",keywords:b},e={className:"template-variable",variants:[{begin:"\\{\\{",end:"\\}\\}"},{begin:"\\{%",end:"%\\}"}],keywords:b},g={className:"string",contains:[a.BACKSLASH_ESCAPE,d],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[Qwi]?\\(",end:"\\)",contains:f("\\(","\\)")},{begin:"%[Qwi]?\\[",end:"\\]",contains:f("\\[","\\]")},{begin:"%[Qwi]?{",end:"}",contains:f("{","}")},{begin:"%[Qwi]?<",end:">",contains:f("<",">")},{begin:"%[Qwi]?\\|",
 end:"\\|"},{begin:/<<-\w+$/,end:/^\s*\w+$/}],relevance:0},k={className:"string",variants:[{begin:"%q\\(",end:"\\)",contains:f("\\(","\\)")},{begin:"%q\\[",end:"\\]",contains:f("\\[","\\]")},{begin:"%q{",end:"}",contains:f("{","}")},{begin:"%q<",end:">",contains:f("<",">")},{begin:"%q\\|",end:"\\|"},{begin:/<<-'\w+'$/,end:/^\s*\w+$/}],relevance:0},p={begin:"(?!%})("+a.RE_STARTERS_RE+"|\\n|\\b(case|if|select|unless|until|when|while)\\b)\\s*",keywords:"case if select unless until when while",contains:[{className:"regexp",
 contains:[a.BACKSLASH_ESCAPE,d],variants:[{begin:"//[a-z]*",relevance:0},{begin:"/(?!\\/)",end:"/[a-z]*"}]}],relevance:0},r={className:"regexp",contains:[a.BACKSLASH_ESCAPE,d],variants:[{begin:"%r\\(",end:"\\)",contains:f("\\(","\\)")},{begin:"%r\\[",end:"\\]",contains:f("\\[","\\]")},{begin:"%r{",end:"}",contains:f("{","}")},{begin:"%r<",end:">",contains:f("<",">")},{begin:"%r\\|",end:"\\|"}],relevance:0},h={className:"meta",begin:"@\\[",end:"\\]",contains:[a.inherit(a.QUOTE_STRING_MODE,{className:"meta-string"})]};
 a=[e,g,k,r,p,h,a.HASH_COMMENT_MODE,{className:"class",beginKeywords:"class module struct",end:"$|;",illegal:/=/,contains:[a.HASH_COMMENT_MODE,a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<"}]},{className:"class",beginKeywords:"lib enum union",end:"$|;",illegal:/=/,contains:[a.HASH_COMMENT_MODE,a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"})],relevance:10},{beginKeywords:"annotation",end:"$|;",illegal:/=/,contains:[a.HASH_COMMENT_MODE,a.inherit(a.TITLE_MODE,
 {begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"})],relevance:10},{className:"function",beginKeywords:"def",end:/\B\b/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|[=!]~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~|]|//|//=|&[-+*]=?|&\\*\\*|\\[\\][=?]?",endsParent:!0})]},{className:"function",beginKeywords:"fun macro",end:/\B\b/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|[=!]~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~|]|//|//=|&[-+*]=?|&\\*\\*|\\[\\][=?]?",endsParent:!0})],
 relevance:5},{className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":",contains:[g,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|[=!]~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~|]|//|//=|&[-+*]=?|&\\*\\*|\\[\\][=?]?"}],relevance:0},{className:"number",variants:[{begin:"\\b0b([01_]+)(_*[ui](8|16|32|64|128))?"},{begin:"\\b0o([0-7_]+)(_*[ui](8|16|32|64|128))?"},{begin:"\\b0x([A-Fa-f0-9_]+)(_*[ui](8|16|32|64|128))?"},{begin:"\\b([1-9][0-9_]*[0-9]|[0-9])(\\.[0-9][0-9_]*)?([eE]_*[-+]?[0-9_]*)?(_*f(32|64))?(?!_)"},
-{begin:"\\b([1-9][0-9_]*|0)(_*[ui](8|16|32|64|128))?"}],relevance:0}];d.contains=a;e.contains=a.slice(1);return{aliases:["cr"],lexemes:"[a-zA-Z_]\\w*[!?=]?",keywords:b,contains:a}});b.registerLanguage("cs",function(a){var f={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield",
-literal:"null false true"},b={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},d={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},e=a.inherit(d,{illegal:/\n/}),g={className:"subst",begin:"{",end:"}",keywords:f},k=a.inherit(g,{illegal:/\n/}),p={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},
-{begin:"}}"},a.BACKSLASH_ESCAPE,k]},r={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},g]},h=a.inherit(r,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},k]});g.contains=[r,p,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,b,a.C_BLOCK_COMMENT_MODE];k.contains=[h,p,e,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,b,a.inherit(a.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];d={variants:[r,p,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]};e=a.IDENT_RE+"(<"+a.IDENT_RE+"(\\s*,\\s*"+
-a.IDENT_RE+")*>)?(\\[\\])?";return{aliases:["csharp","c#"],keywords:f,illegal:/::/,contains:[a.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:"</?",end:">"}]}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,b,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,
+{begin:"\\b([1-9][0-9_]*|0)(_*[ui](8|16|32|64|128))?"}],relevance:0}];d.contains=a;e.contains=a.slice(1);return{aliases:["cr"],lexemes:"[a-zA-Z_]\\w*[!?=]?",keywords:b,contains:a}});b.registerLanguage("cs",function(a){var b={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let nameof on orderby partial remove select set value var when where yield",
+literal:"null false true"},c={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},d={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},e=a.inherit(d,{illegal:/\n/}),g={className:"subst",begin:"{",end:"}",keywords:b},k=a.inherit(g,{illegal:/\n/}),p={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},
+{begin:"}}"},a.BACKSLASH_ESCAPE,k]},r={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},g]},h=a.inherit(r,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},k]});g.contains=[r,p,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,c,a.C_BLOCK_COMMENT_MODE];k.contains=[h,p,e,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,c,a.inherit(a.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];d={variants:[r,p,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]};e=a.IDENT_RE+"(<"+a.IDENT_RE+"(\\s*,\\s*"+
+a.IDENT_RE+")*>)?(\\[\\])?";return{aliases:["csharp","c#"],keywords:b,illegal:/::/,contains:[a.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:"</?",end:">"}]}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,c,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:,]/,
 contains:[a.TITLE_MODE,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"meta-string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+e+"\\s+)+"+a.IDENT_RE+"\\s*\\(",returnBegin:!0,
-end:/\s*[{;=]/,excludeEnd:!0,keywords:f,contains:[{begin:a.IDENT_RE+"\\s*\\(",returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:f,relevance:0,contains:[d,b,a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}]}});b.registerLanguage("csp",function(a){return{case_insensitive:!1,lexemes:"[a-zA-Z][a-zA-Z0-9_-]*",keywords:{keyword:"base-uri child-src connect-src default-src font-src form-action frame-ancestors frame-src img-src media-src object-src plugin-types report-uri sandbox script-src style-src"},
+end:/\s*[{;=]/,excludeEnd:!0,keywords:b,contains:[{begin:a.IDENT_RE+"\\s*\\(",returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,relevance:0,contains:[d,c,a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}]}});b.registerLanguage("csp",function(a){return{case_insensitive:!1,lexemes:"[a-zA-Z][a-zA-Z0-9_-]*",keywords:{keyword:"base-uri child-src connect-src default-src font-src form-action frame-ancestors frame-src img-src media-src object-src plugin-types report-uri sandbox script-src style-src"},
 contains:[{className:"string",begin:"'",end:"'"},{className:"attribute",begin:"^Content",end:":",excludeEnd:!0}]}});b.registerLanguage("css",function(a){return{case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[a.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9_\-\+\(\)"'.]+/},
 {begin:"@(page|font-face)",lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]",illegal:/:/,returnBegin:!0,contains:[{className:"keyword",begin:/@\-?\w[\w]*(\-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/,className:"attribute"},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[a.C_BLOCK_COMMENT_MODE,
 {begin:/(?:[A-Z_\.\-]+|--[a-zA-Z0-9_-]+)\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.CSS_NUMBER_MODE]}]},a.CSS_NUMBER_MODE,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,a.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",
@@ -155,23 +155,25 @@
 contains:[a.BACKSLASH_ESCAPE]},{begin:"'\\\\?.",end:"'",illegal:"."}]},c={className:"number",variants:[{begin:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},{begin:a.C_NUMBER_RE}],relevance:0},d={className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef ifdef ifndef"},contains:[{begin:/\\\n/,relevance:0},{beginKeywords:"include",end:"$",keywords:{"meta-keyword":"include"},contains:[a.inherit(b,{className:"meta-string"}),{className:"meta-string",begin:"<",end:">",
 illegal:"\\n"}]},b,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},e={className:"variable",begin:"\\&[a-z\\d_]*\\b"},g={className:"meta-keyword",begin:"/[a-z][a-z\\d-]*/"},k={className:"symbol",begin:"^\\s*[a-zA-Z_][a-zA-Z\\d_]*:"},p={className:"params",begin:"<",end:">",contains:[c,e]},r={className:"class",begin:/[a-zA-Z_][a-zA-Z\d_@]*\s{/,end:/[{;=]/,returnBegin:!0,excludeEnd:!0};return{keywords:"",contains:[{className:"class",begin:"/\\s*{",end:"};",relevance:10,contains:[e,g,k,r,p,a.C_LINE_COMMENT_MODE,
 a.C_BLOCK_COMMENT_MODE,c,b]},e,g,k,r,p,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,c,b,d,{begin:a.IDENT_RE+"::",keywords:""}]}});b.registerLanguage("dust",function(a){return{aliases:["dst"],case_insensitive:!0,subLanguage:"xml",contains:[{className:"template-tag",begin:/\{[#\/]/,end:/\}/,illegal:/;/,contains:[{className:"name",begin:/[a-zA-Z\.-]+/,starts:{endsWithParent:!0,relevance:0,contains:[a.QUOTE_STRING_MODE]}}]},{className:"template-variable",begin:/\{/,end:/\}/,illegal:/;/,keywords:"if eq ne lt lte gt gte select default math sep"}]}});
-b.registerLanguage("ebnf",function(a){var b=a.COMMENT(/\(\*/,/\*\)/);return{illegal:/\S/,contains:[b,{className:"attribute",begin:/^[ ]*[a-zA-Z][a-zA-Z-]*([\s-]+[a-zA-Z][a-zA-Z]*)*/},{begin:/=/,end:/;/,contains:[b,{className:"meta",begin:/\?.*\?/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]}]}});b.registerLanguage("elixir",function(a){var b={className:"subst",begin:"#\\{",end:"}",lexemes:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",keywords:"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0"},
-c={className:"string",contains:[a.BACKSLASH_ESCAPE,b],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/}]},d={className:"function",beginKeywords:"def defp defmacro",end:/\B\b/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",endsParent:!0})]},e=a.inherit(d,{className:"class",beginKeywords:"defimpl defmodule defprotocol defrecord",end:/\bdo\b|$|;/});a=[c,a.HASH_COMMENT_MODE,e,d,{begin:"::"},{className:"symbol",begin:":(?![\\s:])",contains:[c,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],
-relevance:0},{className:"symbol",begin:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?:(?!:)",relevance:0},{className:"number",begin:"(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(.[0-9_]+([eE][-+]?[0-9]+)?)?)",relevance:0},{className:"variable",begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{begin:"->"},{begin:"("+a.RE_STARTERS_RE+")\\s*",contains:[a.HASH_COMMENT_MODE,{className:"regexp",illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b],variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}],
-relevance:0}];b.contains=a;return{lexemes:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",keywords:"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0",contains:a}});b.registerLanguage("elm",function(a){var b={variants:[a.COMMENT("--","$"),a.COMMENT("{-","-}",{contains:["self"]})]},c={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},d={begin:"\\(",end:"\\)",illegal:'"',
-contains:[{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},b]};return{keywords:"let in if then else case of where module import exposing type alias as infix infixl infixr port effect command subscription",contains:[{beginKeywords:"port effect module",end:"exposing",keywords:"port effect module where command subscription exposing",contains:[d,b],illegal:"\\W\\.|;"},{begin:"import",end:"$",keywords:"import as exposing",contains:[d,b],illegal:"\\W\\.|;"},{begin:"type",end:"$",keywords:"type alias",
-contains:[c,d,{begin:"{",end:"}",contains:d.contains},b]},{beginKeywords:"infix infixl infixr",end:"$",contains:[a.C_NUMBER_MODE,b]},{begin:"port",end:"$",keywords:"port",contains:[b]},{className:"string",begin:"'\\\\?.",end:"'",illegal:"."},a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,c,a.inherit(a.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),b,{begin:"->|<-"}],illegal:/;/}});b.registerLanguage("ruby",function(a){var b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",
-literal:"true false nil"},c={className:"doctag",begin:"@[A-Za-z]+"},d={begin:"#<",end:">"};c=[a.COMMENT("#","$",{contains:[c]}),a.COMMENT("^\\=begin","^\\=end",{contains:[c],relevance:10}),a.COMMENT("^__END__","\\n$")];var e={className:"subst",begin:"#\\{",end:"}",keywords:b},g={className:"string",contains:[a.BACKSLASH_ESCAPE,e],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",
-end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},{begin:/\w+/,endSameAsBegin:!0,contains:[a.BACKSLASH_ESCAPE,e]}]}]},k={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:b};a=[g,d,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,
-contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE}]}].concat(c)},{className:"function",beginKeywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}),k].concat(c)},{begin:a.IDENT_RE+"::"},{className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[g,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],
-relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:b},{begin:"("+a.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[d,{className:"regexp",contains:[a.BACKSLASH_ESCAPE,e],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(c),
-relevance:0}].concat(c);e.contains=a;k.contains=a;return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:b,illegal:/\/\*/,contains:c.concat([{begin:/^\s*=>/,starts:{end:"$",contains:a}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:a}}]).concat(a)}});b.registerLanguage("erb",function(a){return{subLanguage:"xml",contains:[a.COMMENT("<%#","%>"),{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,
-excludeEnd:!0}]}});b.registerLanguage("erlang-repl",function(a){return{keywords:{built_in:"spawn spawn_link self",keyword:"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor"},contains:[{className:"meta",begin:"^[0-9]+> ",relevance:10},a.COMMENT("%","$"),{className:"number",begin:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",relevance:0},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{begin:"\\?(::)?([A-Z]\\w*(::)?)+"},
-{begin:"->"},{begin:"ok"},{begin:"!"},{begin:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",relevance:0},{begin:"[A-Z][a-zA-Z0-9_']*",relevance:0}]}});b.registerLanguage("erlang",function(a){var b={keyword:"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor",literal:"false true"},c=a.COMMENT("%","$"),d={className:"number",begin:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",relevance:0},
-e={begin:"fun\\s+[a-z'][a-zA-Z0-9_']*/\\d+"},g={begin:"([a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*|[a-z'][a-zA-Z0-9_']*)\\(",end:"\\)",returnBegin:!0,relevance:0,contains:[{begin:"([a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*|[a-z'][a-zA-Z0-9_']*)",relevance:0},{begin:"\\(",end:"\\)",endsWithParent:!0,returnEnd:!0,relevance:0}]},k={begin:"{",end:"}",relevance:0},p={begin:"\\b_([A-Z][A-Za-z0-9_]*)?",relevance:0},r={begin:"[A-Z][a-zA-Z0-9_]*",relevance:0},h={begin:"#"+a.UNDERSCORE_IDENT_RE,relevance:0,
-returnBegin:!0,contains:[{begin:"#"+a.UNDERSCORE_IDENT_RE,relevance:0},{begin:"{",end:"}",relevance:0}]},m={beginKeywords:"fun receive if try case",end:"end",keywords:b};m.contains=[c,e,a.inherit(a.APOS_STRING_MODE,{className:""}),m,g,a.QUOTE_STRING_MODE,d,k,p,r,h];e=[c,e,m,g,a.QUOTE_STRING_MODE,d,k,p,r,h];g.contains[1].contains=e;k.contains=e;h.contains[1].contains=e;g={className:"params",begin:"\\(",end:"\\)",contains:e};return{aliases:["erl"],keywords:b,illegal:"(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))",
-contains:[{className:"function",begin:"^[a-z'][a-zA-Z0-9_']*\\s*\\(",end:"->",returnBegin:!0,illegal:"\\(|#|//|/\\*|\\\\|:|;",contains:[g,a.inherit(a.TITLE_MODE,{begin:"[a-z'][a-zA-Z0-9_']*"})],starts:{end:";|\\.",keywords:b,contains:e}},c,{begin:"^-",end:"\\.",relevance:0,excludeEnd:!0,returnBegin:!0,lexemes:"-"+a.IDENT_RE,keywords:"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec",
-contains:[g]},d,a.QUOTE_STRING_MODE,h,p,r,k,{begin:/\.$/}]}});b.registerLanguage("excel",function(a){return{aliases:["xlsx","xls"],case_insensitive:!0,lexemes:/[a-zA-Z][\w\.]*/,keywords:{built_in:"ABS ACCRINT ACCRINTM ACOS ACOSH ACOT ACOTH AGGREGATE ADDRESS AMORDEGRC AMORLINC AND ARABIC AREAS ASC ASIN ASINH ATAN ATAN2 ATANH AVEDEV AVERAGE AVERAGEA AVERAGEIF AVERAGEIFS BAHTTEXT BASE BESSELI BESSELJ BESSELK BESSELY BETADIST BETA.DIST BETAINV BETA.INV BIN2DEC BIN2HEX BIN2OCT BINOMDIST BINOM.DIST BINOM.DIST.RANGE BINOM.INV BITAND BITLSHIFT BITOR BITRSHIFT BITXOR CALL CEILING CEILING.MATH CEILING.PRECISE CELL CHAR CHIDIST CHIINV CHITEST CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT CHISQ.TEST CHOOSE CLEAN CODE COLUMN COLUMNS COMBIN COMBINA COMPLEX CONCAT CONCATENATE CONFIDENCE CONFIDENCE.NORM CONFIDENCE.T CONVERT CORREL COS COSH COT COTH COUNT COUNTA COUNTBLANK COUNTIF COUNTIFS COUPDAYBS COUPDAYS COUPDAYSNC COUPNCD COUPNUM COUPPCD COVAR COVARIANCE.P COVARIANCE.S CRITBINOM CSC CSCH CUBEKPIMEMBER CUBEMEMBER CUBEMEMBERPROPERTY CUBERANKEDMEMBER CUBESET CUBESETCOUNT CUBEVALUE CUMIPMT CUMPRINC DATE DATEDIF DATEVALUE DAVERAGE DAY DAYS DAYS360 DB DBCS DCOUNT DCOUNTA DDB DEC2BIN DEC2HEX DEC2OCT DECIMAL DEGREES DELTA DEVSQ DGET DISC DMAX DMIN DOLLAR DOLLARDE DOLLARFR DPRODUCT DSTDEV DSTDEVP DSUM DURATION DVAR DVARP EDATE EFFECT ENCODEURL EOMONTH ERF ERF.PRECISE ERFC ERFC.PRECISE ERROR.TYPE EUROCONVERT EVEN EXACT EXP EXPON.DIST EXPONDIST FACT FACTDOUBLE FALSE|0 F.DIST FDIST F.DIST.RT FILTERXML FIND FINDB F.INV F.INV.RT FINV FISHER FISHERINV FIXED FLOOR FLOOR.MATH FLOOR.PRECISE FORECAST FORECAST.ETS FORECAST.ETS.CONFINT FORECAST.ETS.SEASONALITY FORECAST.ETS.STAT FORECAST.LINEAR FORMULATEXT FREQUENCY F.TEST FTEST FV FVSCHEDULE GAMMA GAMMA.DIST GAMMADIST GAMMA.INV GAMMAINV GAMMALN GAMMALN.PRECISE GAUSS GCD GEOMEAN GESTEP GETPIVOTDATA GROWTH HARMEAN HEX2BIN HEX2DEC HEX2OCT HLOOKUP HOUR HYPERLINK HYPGEOM.DIST HYPGEOMDIST IF IFERROR IFNA IFS IMABS IMAGINARY IMARGUMENT IMCONJUGATE IMCOS IMCOSH IMCOT IMCSC IMCSCH IMDIV IMEXP IMLN IMLOG10 IMLOG2 IMPOWER IMPRODUCT IMREAL IMSEC IMSECH IMSIN IMSINH IMSQRT IMSUB IMSUM IMTAN INDEX INDIRECT INFO INT INTERCEPT INTRATE IPMT IRR ISBLANK ISERR ISERROR ISEVEN ISFORMULA ISLOGICAL ISNA ISNONTEXT ISNUMBER ISODD ISREF ISTEXT ISO.CEILING ISOWEEKNUM ISPMT JIS KURT LARGE LCM LEFT LEFTB LEN LENB LINEST LN LOG LOG10 LOGEST LOGINV LOGNORM.DIST LOGNORMDIST LOGNORM.INV LOOKUP LOWER MATCH MAX MAXA MAXIFS MDETERM MDURATION MEDIAN MID MIDBs MIN MINIFS MINA MINUTE MINVERSE MIRR MMULT MOD MODE MODE.MULT MODE.SNGL MONTH MROUND MULTINOMIAL MUNIT N NA NEGBINOM.DIST NEGBINOMDIST NETWORKDAYS NETWORKDAYS.INTL NOMINAL NORM.DIST NORMDIST NORMINV NORM.INV NORM.S.DIST NORMSDIST NORM.S.INV NORMSINV NOT NOW NPER NPV NUMBERVALUE OCT2BIN OCT2DEC OCT2HEX ODD ODDFPRICE ODDFYIELD ODDLPRICE ODDLYIELD OFFSET OR PDURATION PEARSON PERCENTILE.EXC PERCENTILE.INC PERCENTILE PERCENTRANK.EXC PERCENTRANK.INC PERCENTRANK PERMUT PERMUTATIONA PHI PHONETIC PI PMT POISSON.DIST POISSON POWER PPMT PRICE PRICEDISC PRICEMAT PROB PRODUCT PROPER PV QUARTILE QUARTILE.EXC QUARTILE.INC QUOTIENT RADIANS RAND RANDBETWEEN RANK.AVG RANK.EQ RANK RATE RECEIVED REGISTER.ID REPLACE REPLACEB REPT RIGHT RIGHTB ROMAN ROUND ROUNDDOWN ROUNDUP ROW ROWS RRI RSQ RTD SEARCH SEARCHB SEC SECH SECOND SERIESSUM SHEET SHEETS SIGN SIN SINH SKEW SKEW.P SLN SLOPE SMALL SQL.REQUEST SQRT SQRTPI STANDARDIZE STDEV STDEV.P STDEV.S STDEVA STDEVP STDEVPA STEYX SUBSTITUTE SUBTOTAL SUM SUMIF SUMIFS SUMPRODUCT SUMSQ SUMX2MY2 SUMX2PY2 SUMXMY2 SWITCH SYD T TAN TANH TBILLEQ TBILLPRICE TBILLYIELD T.DIST T.DIST.2T T.DIST.RT TDIST TEXT TEXTJOIN TIME TIMEVALUE T.INV T.INV.2T TINV TODAY TRANSPOSE TREND TRIM TRIMMEAN TRUE|0 TRUNC T.TEST TTEST TYPE UNICHAR UNICODE UPPER VALUE VAR VAR.P VAR.S VARA VARP VARPA VDB VLOOKUP WEBSERVICE WEEKDAY WEEKNUM WEIBULL WEIBULL.DIST WORKDAY WORKDAY.INTL XIRR XNPV XOR YEAR YEARFRAC YIELD YIELDDISC YIELDMAT Z.TEST ZTEST"},
+b.registerLanguage("ebnf",function(a){var b=a.COMMENT(/\(\*/,/\*\)/);return{illegal:/\S/,contains:[b,{className:"attribute",begin:/^[ ]*[a-zA-Z][a-zA-Z-_]*([\s-_]+[a-zA-Z][a-zA-Z]*)*/},{begin:/=/,end:/[.;]/,contains:[b,{className:"meta",begin:/\?.*\?/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]}]}});b.registerLanguage("elixir",function(a){var b={className:"subst",begin:"#\\{",end:"}",lexemes:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",keywords:"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0"},
+c={className:"string",begin:"~[a-z](?=[/|([{<\"'])",contains:[{endsParent:!0,contains:[{contains:[a.BACKSLASH_ESCAPE,b],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/\//,end:/\//},{begin:/\|/,end:/\|/},{begin:/\(/,end:/\)/},{begin:/\[/,end:/\]/},{begin:/\{/,end:/\}/},{begin:/</,end:/>/}]}]}]},d={className:"string",contains:[a.BACKSLASH_ESCAPE,b],variants:[{begin:/"""/,end:/"""/},{begin:/'''/,end:/'''/},{begin:/~S"""/,end:/"""/,contains:[]},{begin:/~S"/,end:/"/,contains:[]},{begin:/~S'''/,
+end:/'''/,contains:[]},{begin:/~S'/,end:/'/,contains:[]},{begin:/'/,end:/'/},{begin:/"/,end:/"/}]},e={className:"function",beginKeywords:"def defp defmacro",end:/\B\b/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",endsParent:!0})]},g=a.inherit(e,{className:"class",beginKeywords:"defimpl defmodule defprotocol defrecord",end:/\bdo\b|$|;/});a=[d,{className:"string",begin:"~[A-Z](?=[/|([{<\"'])",contains:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/\//,end:/\//},{begin:/\|/,
+end:/\|/},{begin:/\(/,end:/\)/},{begin:/\[/,end:/\]/},{begin:/\{/,end:/\}/},{begin:/</,end:/>/}]},c,a.HASH_COMMENT_MODE,g,e,{begin:"::"},{className:"symbol",begin:":(?![\\s:])",contains:[d,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],relevance:0},{className:"symbol",begin:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?:(?!:)",relevance:0},{className:"number",begin:"(\\b0o[0-7_]+)|(\\b0b[01_]+)|(\\b0x[0-9a-fA-F_]+)|(-?\\b[1-9][0-9_]*(.[0-9_]+([eE][-+]?[0-9]+)?)?)",
+relevance:0},{className:"variable",begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{begin:"->"},{begin:"("+a.RE_STARTERS_RE+")\\s*",contains:[a.HASH_COMMENT_MODE,{className:"regexp",illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b],variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}],relevance:0}];b.contains=a;return{lexemes:"[a-zA-Z_][a-zA-Z0-9_.]*(\\!|\\?)?",keywords:"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote require import with|0",
+contains:a}});b.registerLanguage("elm",function(a){var b={variants:[a.COMMENT("--","$"),a.COMMENT("{-","-}",{contains:["self"]})]},c={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},d={begin:"\\(",end:"\\)",illegal:'"',contains:[{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},b]};return{keywords:"let in if then else case of where module import exposing type alias as infix infixl infixr port effect command subscription",contains:[{beginKeywords:"port effect module",end:"exposing",
+keywords:"port effect module where command subscription exposing",contains:[d,b],illegal:"\\W\\.|;"},{begin:"import",end:"$",keywords:"import as exposing",contains:[d,b],illegal:"\\W\\.|;"},{begin:"type",end:"$",keywords:"type alias",contains:[c,d,{begin:"{",end:"}",contains:d.contains},b]},{beginKeywords:"infix infixl infixr",end:"$",contains:[a.C_NUMBER_MODE,b]},{begin:"port",end:"$",keywords:"port",contains:[b]},{className:"string",begin:"'\\\\?.",end:"'",illegal:"."},a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,
+c,a.inherit(a.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),b,{begin:"->|<-"}],illegal:/;/}});b.registerLanguage("ruby",function(a){var b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={className:"doctag",begin:"@[A-Za-z]+"},d={begin:"#<",end:">"};c=[a.COMMENT("#","$",{contains:[c]}),
+a.COMMENT("^\\=begin","^\\=end",{contains:[c],relevance:10}),a.COMMENT("^__END__","\\n$")];var e={className:"subst",begin:"#\\{",end:"}",keywords:b},g={className:"string",contains:[a.BACKSLASH_ESCAPE,e],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",
+end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{begin:/<<[-~]?'?(\w+)(?:.|\n)*?\n\s*\1\b/,returnBegin:!0,contains:[{begin:/<<[-~]?'?/},{begin:/\w+/,endSameAsBegin:!0,contains:[a.BACKSLASH_ESCAPE,e]}]}]},k={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:b};a=[g,d,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+a.IDENT_RE+
+"::)?"+a.IDENT_RE}]}].concat(c)},{className:"function",beginKeywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}),k].concat(c)},{begin:a.IDENT_RE+"::"},{className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[g,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],relevance:0},{className:"number",
+begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:b},{begin:"("+a.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[d,{className:"regexp",contains:[a.BACKSLASH_ESCAPE,e],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(c),relevance:0}].concat(c);
+e.contains=a;k.contains=a;return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:b,illegal:/\/\*/,contains:c.concat([{begin:/^\s*=>/,starts:{end:"$",contains:a}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:a}}]).concat(a)}});b.registerLanguage("erb",function(a){return{subLanguage:"xml",contains:[a.COMMENT("<%#","%>"),{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0}]}});b.registerLanguage("erlang-repl",
+function(a){return{keywords:{built_in:"spawn spawn_link self",keyword:"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor"},contains:[{className:"meta",begin:"^[0-9]+> ",relevance:10},a.COMMENT("%","$"),{className:"number",begin:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",relevance:0},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{begin:"\\?(::)?([A-Z]\\w*(::)?)+"},{begin:"->"},{begin:"ok"},{begin:"!"},{begin:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",
+relevance:0},{begin:"[A-Z][a-zA-Z0-9_']*",relevance:0}]}});b.registerLanguage("erlang",function(a){var b={keyword:"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor",literal:"false true"},c=a.COMMENT("%","$"),d={className:"number",begin:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",relevance:0},e={begin:"fun\\s+[a-z'][a-zA-Z0-9_']*/\\d+"},g={begin:"([a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*|[a-z'][a-zA-Z0-9_']*)\\(",
+end:"\\)",returnBegin:!0,relevance:0,contains:[{begin:"([a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*|[a-z'][a-zA-Z0-9_']*)",relevance:0},{begin:"\\(",end:"\\)",endsWithParent:!0,returnEnd:!0,relevance:0}]},k={begin:"{",end:"}",relevance:0},p={begin:"\\b_([A-Z][A-Za-z0-9_]*)?",relevance:0},r={begin:"[A-Z][a-zA-Z0-9_]*",relevance:0},h={begin:"#"+a.UNDERSCORE_IDENT_RE,relevance:0,returnBegin:!0,contains:[{begin:"#"+a.UNDERSCORE_IDENT_RE,relevance:0},{begin:"{",end:"}",relevance:0}]},m={beginKeywords:"fun receive if try case",
+end:"end",keywords:b};m.contains=[c,e,a.inherit(a.APOS_STRING_MODE,{className:""}),m,g,a.QUOTE_STRING_MODE,d,k,p,r,h];e=[c,e,m,g,a.QUOTE_STRING_MODE,d,k,p,r,h];g.contains[1].contains=e;k.contains=e;h.contains[1].contains=e;g={className:"params",begin:"\\(",end:"\\)",contains:e};return{aliases:["erl"],keywords:b,illegal:"(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))",contains:[{className:"function",begin:"^[a-z'][a-zA-Z0-9_']*\\s*\\(",end:"->",returnBegin:!0,illegal:"\\(|#|//|/\\*|\\\\|:|;",contains:[g,
+a.inherit(a.TITLE_MODE,{begin:"[a-z'][a-zA-Z0-9_']*"})],starts:{end:";|\\.",keywords:b,contains:e}},c,{begin:"^-",end:"\\.",relevance:0,excludeEnd:!0,returnBegin:!0,lexemes:"-"+a.IDENT_RE,keywords:"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec",contains:[g]},d,a.QUOTE_STRING_MODE,h,p,r,k,{begin:/\.$/}]}});b.registerLanguage("excel",function(a){return{aliases:["xlsx","xls"],case_insensitive:!0,
+lexemes:/[a-zA-Z][\w\.]*/,keywords:{built_in:"ABS ACCRINT ACCRINTM ACOS ACOSH ACOT ACOTH AGGREGATE ADDRESS AMORDEGRC AMORLINC AND ARABIC AREAS ASC ASIN ASINH ATAN ATAN2 ATANH AVEDEV AVERAGE AVERAGEA AVERAGEIF AVERAGEIFS BAHTTEXT BASE BESSELI BESSELJ BESSELK BESSELY BETADIST BETA.DIST BETAINV BETA.INV BIN2DEC BIN2HEX BIN2OCT BINOMDIST BINOM.DIST BINOM.DIST.RANGE BINOM.INV BITAND BITLSHIFT BITOR BITRSHIFT BITXOR CALL CEILING CEILING.MATH CEILING.PRECISE CELL CHAR CHIDIST CHIINV CHITEST CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT CHISQ.TEST CHOOSE CLEAN CODE COLUMN COLUMNS COMBIN COMBINA COMPLEX CONCAT CONCATENATE CONFIDENCE CONFIDENCE.NORM CONFIDENCE.T CONVERT CORREL COS COSH COT COTH COUNT COUNTA COUNTBLANK COUNTIF COUNTIFS COUPDAYBS COUPDAYS COUPDAYSNC COUPNCD COUPNUM COUPPCD COVAR COVARIANCE.P COVARIANCE.S CRITBINOM CSC CSCH CUBEKPIMEMBER CUBEMEMBER CUBEMEMBERPROPERTY CUBERANKEDMEMBER CUBESET CUBESETCOUNT CUBEVALUE CUMIPMT CUMPRINC DATE DATEDIF DATEVALUE DAVERAGE DAY DAYS DAYS360 DB DBCS DCOUNT DCOUNTA DDB DEC2BIN DEC2HEX DEC2OCT DECIMAL DEGREES DELTA DEVSQ DGET DISC DMAX DMIN DOLLAR DOLLARDE DOLLARFR DPRODUCT DSTDEV DSTDEVP DSUM DURATION DVAR DVARP EDATE EFFECT ENCODEURL EOMONTH ERF ERF.PRECISE ERFC ERFC.PRECISE ERROR.TYPE EUROCONVERT EVEN EXACT EXP EXPON.DIST EXPONDIST FACT FACTDOUBLE FALSE|0 F.DIST FDIST F.DIST.RT FILTERXML FIND FINDB F.INV F.INV.RT FINV FISHER FISHERINV FIXED FLOOR FLOOR.MATH FLOOR.PRECISE FORECAST FORECAST.ETS FORECAST.ETS.CONFINT FORECAST.ETS.SEASONALITY FORECAST.ETS.STAT FORECAST.LINEAR FORMULATEXT FREQUENCY F.TEST FTEST FV FVSCHEDULE GAMMA GAMMA.DIST GAMMADIST GAMMA.INV GAMMAINV GAMMALN GAMMALN.PRECISE GAUSS GCD GEOMEAN GESTEP GETPIVOTDATA GROWTH HARMEAN HEX2BIN HEX2DEC HEX2OCT HLOOKUP HOUR HYPERLINK HYPGEOM.DIST HYPGEOMDIST IF IFERROR IFNA IFS IMABS IMAGINARY IMARGUMENT IMCONJUGATE IMCOS IMCOSH IMCOT IMCSC IMCSCH IMDIV IMEXP IMLN IMLOG10 IMLOG2 IMPOWER IMPRODUCT IMREAL IMSEC IMSECH IMSIN IMSINH IMSQRT IMSUB IMSUM IMTAN INDEX INDIRECT INFO INT INTERCEPT INTRATE IPMT IRR ISBLANK ISERR ISERROR ISEVEN ISFORMULA ISLOGICAL ISNA ISNONTEXT ISNUMBER ISODD ISREF ISTEXT ISO.CEILING ISOWEEKNUM ISPMT JIS KURT LARGE LCM LEFT LEFTB LEN LENB LINEST LN LOG LOG10 LOGEST LOGINV LOGNORM.DIST LOGNORMDIST LOGNORM.INV LOOKUP LOWER MATCH MAX MAXA MAXIFS MDETERM MDURATION MEDIAN MID MIDBs MIN MINIFS MINA MINUTE MINVERSE MIRR MMULT MOD MODE MODE.MULT MODE.SNGL MONTH MROUND MULTINOMIAL MUNIT N NA NEGBINOM.DIST NEGBINOMDIST NETWORKDAYS NETWORKDAYS.INTL NOMINAL NORM.DIST NORMDIST NORMINV NORM.INV NORM.S.DIST NORMSDIST NORM.S.INV NORMSINV NOT NOW NPER NPV NUMBERVALUE OCT2BIN OCT2DEC OCT2HEX ODD ODDFPRICE ODDFYIELD ODDLPRICE ODDLYIELD OFFSET OR PDURATION PEARSON PERCENTILE.EXC PERCENTILE.INC PERCENTILE PERCENTRANK.EXC PERCENTRANK.INC PERCENTRANK PERMUT PERMUTATIONA PHI PHONETIC PI PMT POISSON.DIST POISSON POWER PPMT PRICE PRICEDISC PRICEMAT PROB PRODUCT PROPER PV QUARTILE QUARTILE.EXC QUARTILE.INC QUOTIENT RADIANS RAND RANDBETWEEN RANK.AVG RANK.EQ RANK RATE RECEIVED REGISTER.ID REPLACE REPLACEB REPT RIGHT RIGHTB ROMAN ROUND ROUNDDOWN ROUNDUP ROW ROWS RRI RSQ RTD SEARCH SEARCHB SEC SECH SECOND SERIESSUM SHEET SHEETS SIGN SIN SINH SKEW SKEW.P SLN SLOPE SMALL SQL.REQUEST SQRT SQRTPI STANDARDIZE STDEV STDEV.P STDEV.S STDEVA STDEVP STDEVPA STEYX SUBSTITUTE SUBTOTAL SUM SUMIF SUMIFS SUMPRODUCT SUMSQ SUMX2MY2 SUMX2PY2 SUMXMY2 SWITCH SYD T TAN TANH TBILLEQ TBILLPRICE TBILLYIELD T.DIST T.DIST.2T T.DIST.RT TDIST TEXT TEXTJOIN TIME TIMEVALUE T.INV T.INV.2T TINV TODAY TRANSPOSE TREND TRIM TRIMMEAN TRUE|0 TRUNC T.TEST TTEST TYPE UNICHAR UNICODE UPPER VALUE VAR VAR.P VAR.S VARA VARP VARPA VDB VLOOKUP WEBSERVICE WEEKDAY WEEKNUM WEIBULL WEIBULL.DIST WORKDAY WORKDAY.INTL XIRR XNPV XOR YEAR YEARFRAC YIELD YIELDDISC YIELDMAT Z.TEST ZTEST"},
 contains:[{begin:/^=/,end:/[^=]/,returnEnd:!0,illegal:/=/,relevance:10},{className:"symbol",begin:/\b[A-Z]{1,2}\d+\b/,end:/[^\d]/,excludeEnd:!0,relevance:0},{className:"symbol",begin:/[A-Z]{0,2}\d*:[A-Z]{0,2}\d*/,relevance:0},a.BACKSLASH_ESCAPE,a.QUOTE_STRING_MODE,{className:"number",begin:a.NUMBER_RE+"(%)?",relevance:0},a.COMMENT(/\bN\(/,/\)/,{excludeBegin:!0,excludeEnd:!0,illegal:/\n/})]}});b.registerLanguage("fix",function(a){return{contains:[{begin:/[^\u2401\u0001]+/,end:/[\u2401\u0001]/,excludeEnd:!0,
 returnBegin:!0,returnEnd:!1,contains:[{begin:/([^\u2401\u0001=]+)/,end:/=([^\u2401\u0001=]+)/,returnEnd:!0,returnBegin:!1,className:"attr"},{begin:/=/,end:/([\u2401\u0001])/,excludeEnd:!0,excludeBegin:!0,className:"string"}]}],case_insensitive:!0}});b.registerLanguage("flix",function(a){return{keywords:{literal:"true false",keyword:"case class def else enum if impl import in lat rel index let match namespace switch type yield with"},contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",
 begin:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},{className:"string",variants:[{begin:'"',end:'"'}]},{className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[{className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/}]},a.C_NUMBER_MODE]}});b.registerLanguage("fortran",function(a){return{case_insensitive:!0,aliases:["f90","f95"],keywords:{literal:".False. .True.",keyword:"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data",
@@ -195,13 +197,12 @@
 keywords:"Feature Background Ability Business Need Scenario Scenarios Scenario Outline Scenario Template Examples Given And Then But When",contains:[{className:"symbol",begin:"\\*",relevance:0},{className:"meta",begin:"@[^@\\s]+"},{begin:"\\|",end:"\\|\\w*$",contains:[{className:"string",begin:"[^|]+"}]},{className:"variable",begin:"<",end:">"},a.HASH_COMMENT_MODE,{className:"string",begin:'"""',end:'"""'},a.QUOTE_STRING_MODE]}});b.registerLanguage("glsl",function(a){return{keywords:{keyword:"break continue discard do else for if return while switch case default attribute binding buffer ccw centroid centroid varying coherent column_major const cw depth_any depth_greater depth_less depth_unchanged early_fragment_tests equal_spacing flat fractional_even_spacing fractional_odd_spacing highp in index inout invariant invocations isolines layout line_strip lines lines_adjacency local_size_x local_size_y local_size_z location lowp max_vertices mediump noperspective offset origin_upper_left out packed patch pixel_center_integer point_mode points precise precision quads r11f_g11f_b10f r16 r16_snorm r16f r16i r16ui r32f r32i r32ui r8 r8_snorm r8i r8ui readonly restrict rg16 rg16_snorm rg16f rg16i rg16ui rg32f rg32i rg32ui rg8 rg8_snorm rg8i rg8ui rgb10_a2 rgb10_a2ui rgba16 rgba16_snorm rgba16f rgba16i rgba16ui rgba32f rgba32i rgba32ui rgba8 rgba8_snorm rgba8i rgba8ui row_major sample shared smooth std140 std430 stream triangle_strip triangles triangles_adjacency uniform varying vertices volatile writeonly",
 type:"atomic_uint bool bvec2 bvec3 bvec4 dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 dmat4x4 double dvec2 dvec3 dvec4 float iimage1D iimage1DArray iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBufferiimageCube iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect image3D imageBuffer imageCube imageCubeArray int isampler1D isampler1DArray isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow image1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint usampler1D usampler1DArray usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D samplerBuffer usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 vec2 vec3 vec4 void",
 built_in:"gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs gl_MaxCombinedTextureImageUnits gl_MaxComputeAtomicCounterBuffers gl_MaxComputeAtomicCounters gl_MaxComputeImageUniforms gl_MaxComputeTextureImageUnits gl_MaxComputeUniformComponents gl_MaxComputeWorkGroupCount gl_MaxComputeWorkGroupSize gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents gl_MaxFragmentInputVectors gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexOutputVectors gl_MaxVertexTextureImageUnits gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffset gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial gl_FrontSecondaryColor gl_GlobalInvocationID gl_InstanceID gl_InvocationID gl_Layer gl_LightModel gl_LightSource gl_LocalInvocationID gl_LocalInvocationIndex gl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix gl_NormalScale gl_NumSamples gl_NumWorkGroups gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor gl_TextureMatrix gl_TextureMatrixInverse gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID gl_ViewportIndex gl_WorkGroupID gl_WorkGroupSize gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive abs acos acosh all any asin asinh atan atanh atomicAdd atomicAnd atomicCompSwap atomicCounter atomicCounterDecrement atomicCounterIncrement atomicExchange atomicMax atomicMin atomicOr atomicXor barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan greaterThanEqual groupMemoryBarrier imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageSize imageStore imulExtended intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier memoryBarrierAtomicCounter memoryBarrierBuffer memoryBarrierImage memoryBarrierShared min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod textureProjLodOffset textureProjOffset textureQueryLevels textureQueryLod textureSize transpose trunc uaddCarry uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 usubBorrow",
-literal:"true false"},illegal:'"',contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.C_NUMBER_MODE,{className:"meta",begin:"#",end:"$"}]}});b.registerLanguage("gml",function(a){return{aliases:["gml","GML"],case_insensitive:!1,keywords:{keywords:"begin end if then else while do for break continue with until repeat exit and or xor not return mod div switch case default var globalvar enum #macro #region #endregion",built_in:"is_real is_string is_array is_undefined is_int32 is_int64 is_ptr is_vec3 is_vec4 is_matrix is_bool typeof variable_global_exists variable_global_get variable_global_set variable_instance_exists variable_instance_get variable_instance_set variable_instance_get_names array_length_1d array_length_2d array_height_2d array_equals array_create array_copy random random_range irandom irandom_range random_set_seed random_get_seed randomize randomise choose abs round floor ceil sign frac sqrt sqr exp ln log2 log10 sin cos tan arcsin arccos arctan arctan2 dsin dcos dtan darcsin darccos darctan darctan2 degtorad radtodeg power logn min max mean median clamp lerp dot_product dot_product_3d dot_product_normalised dot_product_3d_normalised dot_product_normalized dot_product_3d_normalized math_set_epsilon math_get_epsilon angle_difference point_distance_3d point_distance point_direction lengthdir_x lengthdir_y real string int64 ptr string_format chr ansi_char ord string_length string_byte_length string_pos string_copy string_char_at string_ord_at string_byte_at string_set_byte_at string_delete string_insert string_lower string_upper string_repeat string_letters string_digits string_lettersdigits string_replace string_replace_all string_count string_hash_to_newline clipboard_has_text clipboard_set_text clipboard_get_text date_current_datetime date_create_datetime date_valid_datetime date_inc_year date_inc_month date_inc_week date_inc_day date_inc_hour date_inc_minute date_inc_second date_get_year date_get_month date_get_week date_get_day date_get_hour date_get_minute date_get_second date_get_weekday date_get_day_of_year date_get_hour_of_year date_get_minute_of_year date_get_second_of_year date_year_span date_month_span date_week_span date_day_span date_hour_span date_minute_span date_second_span date_compare_datetime date_compare_date date_compare_time date_date_of date_time_of date_datetime_string date_date_string date_time_string date_days_in_month date_days_in_year date_leap_year date_is_today date_set_timezone date_get_timezone game_set_speed game_get_speed motion_set motion_add place_free place_empty place_meeting place_snapped move_random move_snap move_towards_point move_contact_solid move_contact_all move_outside_solid move_outside_all move_bounce_solid move_bounce_all move_wrap distance_to_point distance_to_object position_empty position_meeting path_start path_end mp_linear_step mp_potential_step mp_linear_step_object mp_potential_step_object mp_potential_settings mp_linear_path mp_potential_path mp_linear_path_object mp_potential_path_object mp_grid_create mp_grid_destroy mp_grid_clear_all mp_grid_clear_cell mp_grid_clear_rectangle mp_grid_add_cell mp_grid_get_cell mp_grid_add_rectangle mp_grid_add_instances mp_grid_path mp_grid_draw mp_grid_to_ds_grid collision_point collision_rectangle collision_circle collision_ellipse collision_line collision_point_list collision_rectangle_list collision_circle_list collision_ellipse_list collision_line_list instance_position_list instance_place_list point_in_rectangle point_in_triangle point_in_circle rectangle_in_rectangle rectangle_in_triangle rectangle_in_circle instance_find instance_exists instance_number instance_position instance_nearest instance_furthest instance_place instance_create_depth instance_create_layer instance_copy instance_change instance_destroy position_destroy position_change instance_id_get instance_deactivate_all instance_deactivate_object instance_deactivate_region instance_activate_all instance_activate_object instance_activate_region room_goto room_goto_previous room_goto_next room_previous room_next room_restart game_end game_restart game_load game_save game_save_buffer game_load_buffer event_perform event_user event_perform_object event_inherited show_debug_message show_debug_overlay debug_event debug_get_callstack alarm_get alarm_set font_texture_page_size keyboard_set_map keyboard_get_map keyboard_unset_map keyboard_check keyboard_check_pressed keyboard_check_released keyboard_check_direct keyboard_get_numlock keyboard_set_numlock keyboard_key_press keyboard_key_release keyboard_clear io_clear mouse_check_button mouse_check_button_pressed mouse_check_button_released mouse_wheel_up mouse_wheel_down mouse_clear draw_self draw_sprite draw_sprite_pos draw_sprite_ext draw_sprite_stretched draw_sprite_stretched_ext draw_sprite_tiled draw_sprite_tiled_ext draw_sprite_part draw_sprite_part_ext draw_sprite_general draw_clear draw_clear_alpha draw_point draw_line draw_line_width draw_rectangle draw_roundrect draw_roundrect_ext draw_triangle draw_circle draw_ellipse draw_set_circle_precision draw_arrow draw_button draw_path draw_healthbar draw_getpixel draw_getpixel_ext draw_set_colour draw_set_color draw_set_alpha draw_get_colour draw_get_color draw_get_alpha merge_colour make_colour_rgb make_colour_hsv colour_get_red colour_get_green colour_get_blue colour_get_hue colour_get_saturation colour_get_value merge_color make_color_rgb make_color_hsv color_get_red color_get_green color_get_blue color_get_hue color_get_saturation color_get_value merge_color screen_save screen_save_part draw_set_font draw_set_halign draw_set_valign draw_text draw_text_ext string_width string_height string_width_ext string_height_ext draw_text_transformed draw_text_ext_transformed draw_text_colour draw_text_ext_colour draw_text_transformed_colour draw_text_ext_transformed_colour draw_text_color draw_text_ext_color draw_text_transformed_color draw_text_ext_transformed_color draw_point_colour draw_line_colour draw_line_width_colour draw_rectangle_colour draw_roundrect_colour draw_roundrect_colour_ext draw_triangle_colour draw_circle_colour draw_ellipse_colour draw_point_color draw_line_color draw_line_width_color draw_rectangle_color draw_roundrect_color draw_roundrect_color_ext draw_triangle_color draw_circle_color draw_ellipse_color draw_primitive_begin draw_vertex draw_vertex_colour draw_vertex_color draw_primitive_end sprite_get_uvs font_get_uvs sprite_get_texture font_get_texture texture_get_width texture_get_height texture_get_uvs draw_primitive_begin_texture draw_vertex_texture draw_vertex_texture_colour draw_vertex_texture_color texture_global_scale surface_create surface_create_ext surface_resize surface_free surface_exists surface_get_width surface_get_height surface_get_texture surface_set_target surface_set_target_ext surface_reset_target surface_depth_disable surface_get_depth_disable draw_surface draw_surface_stretched draw_surface_tiled draw_surface_part draw_surface_ext draw_surface_stretched_ext draw_surface_tiled_ext draw_surface_part_ext draw_surface_general surface_getpixel surface_getpixel_ext surface_save surface_save_part surface_copy surface_copy_part application_surface_draw_enable application_get_position application_surface_enable application_surface_is_enabled display_get_width display_get_height display_get_orientation display_get_gui_width display_get_gui_height display_reset display_mouse_get_x display_mouse_get_y display_mouse_set display_set_ui_visibility window_set_fullscreen window_get_fullscreen window_set_caption window_set_min_width window_set_max_width window_set_min_height window_set_max_height window_get_visible_rects window_get_caption window_set_cursor window_get_cursor window_set_colour window_get_colour window_set_color window_get_color window_set_position window_set_size window_set_rectangle window_center window_get_x window_get_y window_get_width window_get_height window_mouse_get_x window_mouse_get_y window_mouse_set window_view_mouse_get_x window_view_mouse_get_y window_views_mouse_get_x window_views_mouse_get_y audio_listener_position audio_listener_velocity audio_listener_orientation audio_emitter_position audio_emitter_create audio_emitter_free audio_emitter_exists audio_emitter_pitch audio_emitter_velocity audio_emitter_falloff audio_emitter_gain audio_play_sound audio_play_sound_on audio_play_sound_at audio_stop_sound audio_resume_music audio_music_is_playing audio_resume_sound audio_pause_sound audio_pause_music audio_channel_num audio_sound_length audio_get_type audio_falloff_set_model audio_play_music audio_stop_music audio_master_gain audio_music_gain audio_sound_gain audio_sound_pitch audio_stop_all audio_resume_all audio_pause_all audio_is_playing audio_is_paused audio_exists audio_sound_set_track_position audio_sound_get_track_position audio_emitter_get_gain audio_emitter_get_pitch audio_emitter_get_x audio_emitter_get_y audio_emitter_get_z audio_emitter_get_vx audio_emitter_get_vy audio_emitter_get_vz audio_listener_set_position audio_listener_set_velocity audio_listener_set_orientation audio_listener_get_data audio_set_master_gain audio_get_master_gain audio_sound_get_gain audio_sound_get_pitch audio_get_name audio_sound_set_track_position audio_sound_get_track_position audio_create_stream audio_destroy_stream audio_create_sync_group audio_destroy_sync_group audio_play_in_sync_group audio_start_sync_group audio_stop_sync_group audio_pause_sync_group audio_resume_sync_group audio_sync_group_get_track_pos audio_sync_group_debug audio_sync_group_is_playing audio_debug audio_group_load audio_group_unload audio_group_is_loaded audio_group_load_progress audio_group_name audio_group_stop_all audio_group_set_gain audio_create_buffer_sound audio_free_buffer_sound audio_create_play_queue audio_free_play_queue audio_queue_sound audio_get_recorder_count audio_get_recorder_info audio_start_recording audio_stop_recording audio_sound_get_listener_mask audio_emitter_get_listener_mask audio_get_listener_mask audio_sound_set_listener_mask audio_emitter_set_listener_mask audio_set_listener_mask audio_get_listener_count audio_get_listener_info audio_system show_message show_message_async clickable_add clickable_add_ext clickable_change clickable_change_ext clickable_delete clickable_exists clickable_set_style show_question show_question_async get_integer get_string get_integer_async get_string_async get_login_async get_open_filename get_save_filename get_open_filename_ext get_save_filename_ext show_error highscore_clear highscore_add highscore_value highscore_name draw_highscore sprite_exists sprite_get_name sprite_get_number sprite_get_width sprite_get_height sprite_get_xoffset sprite_get_yoffset sprite_get_bbox_left sprite_get_bbox_right sprite_get_bbox_top sprite_get_bbox_bottom sprite_save sprite_save_strip sprite_set_cache_size sprite_set_cache_size_ext sprite_get_tpe sprite_prefetch sprite_prefetch_multi sprite_flush sprite_flush_multi sprite_set_speed sprite_get_speed_type sprite_get_speed font_exists font_get_name font_get_fontname font_get_bold font_get_italic font_get_first font_get_last font_get_size font_set_cache_size path_exists path_get_name path_get_length path_get_time path_get_kind path_get_closed path_get_precision path_get_number path_get_point_x path_get_point_y path_get_point_speed path_get_x path_get_y path_get_speed script_exists script_get_name timeline_add timeline_delete timeline_clear timeline_exists timeline_get_name timeline_moment_clear timeline_moment_add_script timeline_size timeline_max_moment object_exists object_get_name object_get_sprite object_get_solid object_get_visible object_get_persistent object_get_mask object_get_parent object_get_physics object_is_ancestor room_exists room_get_name sprite_set_offset sprite_duplicate sprite_assign sprite_merge sprite_add sprite_replace sprite_create_from_surface sprite_add_from_surface sprite_delete sprite_set_alpha_from_sprite sprite_collision_mask font_add_enable_aa font_add_get_enable_aa font_add font_add_sprite font_add_sprite_ext font_replace font_replace_sprite font_replace_sprite_ext font_delete path_set_kind path_set_closed path_set_precision path_add path_assign path_duplicate path_append path_delete path_add_point path_insert_point path_change_point path_delete_point path_clear_points path_reverse path_mirror path_flip path_rotate path_rescale path_shift script_execute object_set_sprite object_set_solid object_set_visible object_set_persistent object_set_mask room_set_width room_set_height room_set_persistent room_set_background_colour room_set_background_color room_set_view room_set_viewport room_get_viewport room_set_view_enabled room_add room_duplicate room_assign room_instance_add room_instance_clear room_get_camera room_set_camera asset_get_index asset_get_type file_text_open_from_string file_text_open_read file_text_open_write file_text_open_append file_text_close file_text_write_string file_text_write_real file_text_writeln file_text_read_string file_text_read_real file_text_readln file_text_eof file_text_eoln file_exists file_delete file_rename file_copy directory_exists directory_create directory_destroy file_find_first file_find_next file_find_close file_attributes filename_name filename_path filename_dir filename_drive filename_ext filename_change_ext file_bin_open file_bin_rewrite file_bin_close file_bin_position file_bin_size file_bin_seek file_bin_write_byte file_bin_read_byte parameter_count parameter_string environment_get_variable ini_open_from_string ini_open ini_close ini_read_string ini_read_real ini_write_string ini_write_real ini_key_exists ini_section_exists ini_key_delete ini_section_delete ds_set_precision ds_exists ds_stack_create ds_stack_destroy ds_stack_clear ds_stack_copy ds_stack_size ds_stack_empty ds_stack_push ds_stack_pop ds_stack_top ds_stack_write ds_stack_read ds_queue_create ds_queue_destroy ds_queue_clear ds_queue_copy ds_queue_size ds_queue_empty ds_queue_enqueue ds_queue_dequeue ds_queue_head ds_queue_tail ds_queue_write ds_queue_read ds_list_create ds_list_destroy ds_list_clear ds_list_copy ds_list_size ds_list_empty ds_list_add ds_list_insert ds_list_replace ds_list_delete ds_list_find_index ds_list_find_value ds_list_mark_as_list ds_list_mark_as_map ds_list_sort ds_list_shuffle ds_list_write ds_list_read ds_list_set ds_map_create ds_map_destroy ds_map_clear ds_map_copy ds_map_size ds_map_empty ds_map_add ds_map_add_list ds_map_add_map ds_map_replace ds_map_replace_map ds_map_replace_list ds_map_delete ds_map_exists ds_map_find_value ds_map_find_previous ds_map_find_next ds_map_find_first ds_map_find_last ds_map_write ds_map_read ds_map_secure_save ds_map_secure_load ds_map_secure_load_buffer ds_map_secure_save_buffer ds_map_set ds_priority_create ds_priority_destroy ds_priority_clear ds_priority_copy ds_priority_size ds_priority_empty ds_priority_add ds_priority_change_priority ds_priority_find_priority ds_priority_delete_value ds_priority_delete_min ds_priority_find_min ds_priority_delete_max ds_priority_find_max ds_priority_write ds_priority_read ds_grid_create ds_grid_destroy ds_grid_copy ds_grid_resize ds_grid_width ds_grid_height ds_grid_clear ds_grid_set ds_grid_add ds_grid_multiply ds_grid_set_region ds_grid_add_region ds_grid_multiply_region ds_grid_set_disk ds_grid_add_disk ds_grid_multiply_disk ds_grid_set_grid_region ds_grid_add_grid_region ds_grid_multiply_grid_region ds_grid_get ds_grid_get_sum ds_grid_get_max ds_grid_get_min ds_grid_get_mean ds_grid_get_disk_sum ds_grid_get_disk_min ds_grid_get_disk_max ds_grid_get_disk_mean ds_grid_value_exists ds_grid_value_x ds_grid_value_y ds_grid_value_disk_exists ds_grid_value_disk_x ds_grid_value_disk_y ds_grid_shuffle ds_grid_write ds_grid_read ds_grid_sort ds_grid_set ds_grid_get effect_create_below effect_create_above effect_clear part_type_create part_type_destroy part_type_exists part_type_clear part_type_shape part_type_sprite part_type_size part_type_scale part_type_orientation part_type_life part_type_step part_type_death part_type_speed part_type_direction part_type_gravity part_type_colour1 part_type_colour2 part_type_colour3 part_type_colour_mix part_type_colour_rgb part_type_colour_hsv part_type_color1 part_type_color2 part_type_color3 part_type_color_mix part_type_color_rgb part_type_color_hsv part_type_alpha1 part_type_alpha2 part_type_alpha3 part_type_blend part_system_create part_system_create_layer part_system_destroy part_system_exists part_system_clear part_system_draw_order part_system_depth part_system_position part_system_automatic_update part_system_automatic_draw part_system_update part_system_drawit part_system_get_layer part_system_layer part_particles_create part_particles_create_colour part_particles_create_color part_particles_clear part_particles_count part_emitter_create part_emitter_destroy part_emitter_destroy_all part_emitter_exists part_emitter_clear part_emitter_region part_emitter_burst part_emitter_stream external_call external_define external_free window_handle window_device matrix_get matrix_set matrix_build_identity matrix_build matrix_build_lookat matrix_build_projection_ortho matrix_build_projection_perspective matrix_build_projection_perspective_fov matrix_multiply matrix_transform_vertex matrix_stack_push matrix_stack_pop matrix_stack_multiply matrix_stack_set matrix_stack_clear matrix_stack_top matrix_stack_is_empty browser_input_capture os_get_config os_get_info os_get_language os_get_region os_lock_orientation display_get_dpi_x display_get_dpi_y display_set_gui_size display_set_gui_maximise display_set_gui_maximize device_mouse_dbclick_enable display_set_timing_method display_get_timing_method display_set_sleep_margin display_get_sleep_margin virtual_key_add virtual_key_hide virtual_key_delete virtual_key_show draw_enable_drawevent draw_enable_swf_aa draw_set_swf_aa_level draw_get_swf_aa_level draw_texture_flush draw_flush gpu_set_blendenable gpu_set_ztestenable gpu_set_zfunc gpu_set_zwriteenable gpu_set_lightingenable gpu_set_fog gpu_set_cullmode gpu_set_blendmode gpu_set_blendmode_ext gpu_set_blendmode_ext_sepalpha gpu_set_colorwriteenable gpu_set_colourwriteenable gpu_set_alphatestenable gpu_set_alphatestref gpu_set_alphatestfunc gpu_set_texfilter gpu_set_texfilter_ext gpu_set_texrepeat gpu_set_texrepeat_ext gpu_set_tex_filter gpu_set_tex_filter_ext gpu_set_tex_repeat gpu_set_tex_repeat_ext gpu_set_tex_mip_filter gpu_set_tex_mip_filter_ext gpu_set_tex_mip_bias gpu_set_tex_mip_bias_ext gpu_set_tex_min_mip gpu_set_tex_min_mip_ext gpu_set_tex_max_mip gpu_set_tex_max_mip_ext gpu_set_tex_max_aniso gpu_set_tex_max_aniso_ext gpu_set_tex_mip_enable gpu_set_tex_mip_enable_ext gpu_get_blendenable gpu_get_ztestenable gpu_get_zfunc gpu_get_zwriteenable gpu_get_lightingenable gpu_get_fog gpu_get_cullmode gpu_get_blendmode gpu_get_blendmode_ext gpu_get_blendmode_ext_sepalpha gpu_get_blendmode_src gpu_get_blendmode_dest gpu_get_blendmode_srcalpha gpu_get_blendmode_destalpha gpu_get_colorwriteenable gpu_get_colourwriteenable gpu_get_alphatestenable gpu_get_alphatestref gpu_get_alphatestfunc gpu_get_texfilter gpu_get_texfilter_ext gpu_get_texrepeat gpu_get_texrepeat_ext gpu_get_tex_filter gpu_get_tex_filter_ext gpu_get_tex_repeat gpu_get_tex_repeat_ext gpu_get_tex_mip_filter gpu_get_tex_mip_filter_ext gpu_get_tex_mip_bias gpu_get_tex_mip_bias_ext gpu_get_tex_min_mip gpu_get_tex_min_mip_ext gpu_get_tex_max_mip gpu_get_tex_max_mip_ext gpu_get_tex_max_aniso gpu_get_tex_max_aniso_ext gpu_get_tex_mip_enable gpu_get_tex_mip_enable_ext gpu_push_state gpu_pop_state gpu_get_state gpu_set_state draw_light_define_ambient draw_light_define_direction draw_light_define_point draw_light_enable draw_set_lighting draw_light_get_ambient draw_light_get draw_get_lighting shop_leave_rating url_get_domain url_open url_open_ext url_open_full get_timer achievement_login achievement_logout achievement_post achievement_increment achievement_post_score achievement_available achievement_show_achievements achievement_show_leaderboards achievement_load_friends achievement_load_leaderboard achievement_send_challenge achievement_load_progress achievement_reset achievement_login_status achievement_get_pic achievement_show_challenge_notifications achievement_get_challenges achievement_event achievement_show achievement_get_info cloud_file_save cloud_string_save cloud_synchronise ads_enable ads_disable ads_setup ads_engagement_launch ads_engagement_available ads_engagement_active ads_event ads_event_preload ads_set_reward_callback ads_get_display_height ads_get_display_width ads_move ads_interstitial_available ads_interstitial_display device_get_tilt_x device_get_tilt_y device_get_tilt_z device_is_keypad_open device_mouse_check_button device_mouse_check_button_pressed device_mouse_check_button_released device_mouse_x device_mouse_y device_mouse_raw_x device_mouse_raw_y device_mouse_x_to_gui device_mouse_y_to_gui iap_activate iap_status iap_enumerate_products iap_restore_all iap_acquire iap_consume iap_product_details iap_purchase_details facebook_init facebook_login facebook_status facebook_graph_request facebook_dialog facebook_logout facebook_launch_offerwall facebook_post_message facebook_send_invite facebook_user_id facebook_accesstoken facebook_check_permission facebook_request_read_permissions facebook_request_publish_permissions gamepad_is_supported gamepad_get_device_count gamepad_is_connected gamepad_get_description gamepad_get_button_threshold gamepad_set_button_threshold gamepad_get_axis_deadzone gamepad_set_axis_deadzone gamepad_button_count gamepad_button_check gamepad_button_check_pressed gamepad_button_check_released gamepad_button_value gamepad_axis_count gamepad_axis_value gamepad_set_vibration gamepad_set_colour gamepad_set_color os_is_paused window_has_focus code_is_compiled http_get http_get_file http_post_string http_request json_encode json_decode zip_unzip load_csv base64_encode base64_decode md5_string_unicode md5_string_utf8 md5_file os_is_network_connected sha1_string_unicode sha1_string_utf8 sha1_file os_powersave_enable analytics_event analytics_event_ext win8_livetile_tile_notification win8_livetile_tile_clear win8_livetile_badge_notification win8_livetile_badge_clear win8_livetile_queue_enable win8_secondarytile_pin win8_secondarytile_badge_notification win8_secondarytile_delete win8_livetile_notification_begin win8_livetile_notification_secondary_begin win8_livetile_notification_expiry win8_livetile_notification_tag win8_livetile_notification_text_add win8_livetile_notification_image_add win8_livetile_notification_end win8_appbar_enable win8_appbar_add_element win8_appbar_remove_element win8_settingscharm_add_entry win8_settingscharm_add_html_entry win8_settingscharm_add_xaml_entry win8_settingscharm_set_xaml_property win8_settingscharm_get_xaml_property win8_settingscharm_remove_entry win8_share_image win8_share_screenshot win8_share_file win8_share_url win8_share_text win8_search_enable win8_search_disable win8_search_add_suggestions win8_device_touchscreen_available win8_license_initialize_sandbox win8_license_trial_version winphone_license_trial_version winphone_tile_title winphone_tile_count winphone_tile_back_title winphone_tile_back_content winphone_tile_back_content_wide winphone_tile_front_image winphone_tile_front_image_small winphone_tile_front_image_wide winphone_tile_back_image winphone_tile_back_image_wide winphone_tile_background_colour winphone_tile_background_color winphone_tile_icon_image winphone_tile_small_icon_image winphone_tile_wide_content winphone_tile_cycle_images winphone_tile_small_background_image physics_world_create physics_world_gravity physics_world_update_speed physics_world_update_iterations physics_world_draw_debug physics_pause_enable physics_fixture_create physics_fixture_set_kinematic physics_fixture_set_density physics_fixture_set_awake physics_fixture_set_restitution physics_fixture_set_friction physics_fixture_set_collision_group physics_fixture_set_sensor physics_fixture_set_linear_damping physics_fixture_set_angular_damping physics_fixture_set_circle_shape physics_fixture_set_box_shape physics_fixture_set_edge_shape physics_fixture_set_polygon_shape physics_fixture_set_chain_shape physics_fixture_add_point physics_fixture_bind physics_fixture_bind_ext physics_fixture_delete physics_apply_force physics_apply_impulse physics_apply_angular_impulse physics_apply_local_force physics_apply_local_impulse physics_apply_torque physics_mass_properties physics_draw_debug physics_test_overlap physics_remove_fixture physics_set_friction physics_set_density physics_set_restitution physics_get_friction physics_get_density physics_get_restitution physics_joint_distance_create physics_joint_rope_create physics_joint_revolute_create physics_joint_prismatic_create physics_joint_pulley_create physics_joint_wheel_create physics_joint_weld_create physics_joint_friction_create physics_joint_gear_create physics_joint_enable_motor physics_joint_get_value physics_joint_set_value physics_joint_delete physics_particle_create physics_particle_delete physics_particle_delete_region_circle physics_particle_delete_region_box physics_particle_delete_region_poly physics_particle_set_flags physics_particle_set_category_flags physics_particle_draw physics_particle_draw_ext physics_particle_count physics_particle_get_data physics_particle_get_data_particle physics_particle_group_begin physics_particle_group_circle physics_particle_group_box physics_particle_group_polygon physics_particle_group_add_point physics_particle_group_end physics_particle_group_join physics_particle_group_delete physics_particle_group_count physics_particle_group_get_data physics_particle_group_get_mass physics_particle_group_get_inertia physics_particle_group_get_centre_x physics_particle_group_get_centre_y physics_particle_group_get_vel_x physics_particle_group_get_vel_y physics_particle_group_get_ang_vel physics_particle_group_get_x physics_particle_group_get_y physics_particle_group_get_angle physics_particle_set_group_flags physics_particle_get_group_flags physics_particle_get_max_count physics_particle_get_radius physics_particle_get_density physics_particle_get_damping physics_particle_get_gravity_scale physics_particle_set_max_count physics_particle_set_radius physics_particle_set_density physics_particle_set_damping physics_particle_set_gravity_scale network_create_socket network_create_socket_ext network_create_server network_create_server_raw network_connect network_connect_raw network_send_packet network_send_raw network_send_broadcast network_send_udp network_send_udp_raw network_set_timeout network_set_config network_resolve network_destroy buffer_create buffer_write buffer_read buffer_seek buffer_get_surface buffer_set_surface buffer_delete buffer_exists buffer_get_type buffer_get_alignment buffer_poke buffer_peek buffer_save buffer_save_ext buffer_load buffer_load_ext buffer_load_partial buffer_copy buffer_fill buffer_get_size buffer_tell buffer_resize buffer_md5 buffer_sha1 buffer_base64_encode buffer_base64_decode buffer_base64_decode_ext buffer_sizeof buffer_get_address buffer_create_from_vertex_buffer buffer_create_from_vertex_buffer_ext buffer_copy_from_vertex_buffer buffer_async_group_begin buffer_async_group_option buffer_async_group_end buffer_load_async buffer_save_async gml_release_mode gml_pragma steam_activate_overlay steam_is_overlay_enabled steam_is_overlay_activated steam_get_persona_name steam_initialised steam_is_cloud_enabled_for_app steam_is_cloud_enabled_for_account steam_file_persisted steam_get_quota_total steam_get_quota_free steam_file_write steam_file_write_file steam_file_read steam_file_delete steam_file_exists steam_file_size steam_file_share steam_is_screenshot_requested steam_send_screenshot steam_is_user_logged_on steam_get_user_steam_id steam_user_owns_dlc steam_user_installed_dlc steam_set_achievement steam_get_achievement steam_clear_achievement steam_set_stat_int steam_set_stat_float steam_set_stat_avg_rate steam_get_stat_int steam_get_stat_float steam_get_stat_avg_rate steam_reset_all_stats steam_reset_all_stats_achievements steam_stats_ready steam_create_leaderboard steam_upload_score steam_upload_score_ext steam_download_scores_around_user steam_download_scores steam_download_friends_scores steam_upload_score_buffer steam_upload_score_buffer_ext steam_current_game_language steam_available_languages steam_activate_overlay_browser steam_activate_overlay_user steam_activate_overlay_store steam_get_user_persona_name steam_get_app_id steam_get_user_account_id steam_ugc_download steam_ugc_create_item steam_ugc_start_item_update steam_ugc_set_item_title steam_ugc_set_item_description steam_ugc_set_item_visibility steam_ugc_set_item_tags steam_ugc_set_item_content steam_ugc_set_item_preview steam_ugc_submit_item_update steam_ugc_get_item_update_progress steam_ugc_subscribe_item steam_ugc_unsubscribe_item steam_ugc_num_subscribed_items steam_ugc_get_subscribed_items steam_ugc_get_item_install_info steam_ugc_get_item_update_info steam_ugc_request_item_details steam_ugc_create_query_user steam_ugc_create_query_user_ex steam_ugc_create_query_all steam_ugc_create_query_all_ex steam_ugc_query_set_cloud_filename_filter steam_ugc_query_set_match_any_tag steam_ugc_query_set_search_text steam_ugc_query_set_ranked_by_trend_days steam_ugc_query_add_required_tag steam_ugc_query_add_excluded_tag steam_ugc_query_set_return_long_description steam_ugc_query_set_return_total_only steam_ugc_query_set_allow_cached_response steam_ugc_send_query shader_set shader_get_name shader_reset shader_current shader_is_compiled shader_get_sampler_index shader_get_uniform shader_set_uniform_i shader_set_uniform_i_array shader_set_uniform_f shader_set_uniform_f_array shader_set_uniform_matrix shader_set_uniform_matrix_array shader_enable_corner_id texture_set_stage texture_get_texel_width texture_get_texel_height shaders_are_supported vertex_format_begin vertex_format_end vertex_format_delete vertex_format_add_position vertex_format_add_position_3d vertex_format_add_colour vertex_format_add_color vertex_format_add_normal vertex_format_add_texcoord vertex_format_add_textcoord vertex_format_add_custom vertex_create_buffer vertex_create_buffer_ext vertex_delete_buffer vertex_begin vertex_end vertex_position vertex_position_3d vertex_colour vertex_color vertex_argb vertex_texcoord vertex_normal vertex_float1 vertex_float2 vertex_float3 vertex_float4 vertex_ubyte4 vertex_submit vertex_freeze vertex_get_number vertex_get_buffer_size vertex_create_buffer_from_buffer vertex_create_buffer_from_buffer_ext push_local_notification push_get_first_local_notification push_get_next_local_notification push_cancel_local_notification skeleton_animation_set skeleton_animation_get skeleton_animation_mix skeleton_animation_set_ext skeleton_animation_get_ext skeleton_animation_get_duration skeleton_animation_get_frames skeleton_animation_clear skeleton_skin_set skeleton_skin_get skeleton_attachment_set skeleton_attachment_get skeleton_attachment_create skeleton_collision_draw_set skeleton_bone_data_get skeleton_bone_data_set skeleton_bone_state_get skeleton_bone_state_set skeleton_get_minmax skeleton_get_num_bounds skeleton_get_bounds skeleton_animation_get_frame skeleton_animation_set_frame draw_skeleton draw_skeleton_time draw_skeleton_instance draw_skeleton_collision skeleton_animation_list skeleton_skin_list skeleton_slot_data layer_get_id layer_get_id_at_depth layer_get_depth layer_create layer_destroy layer_destroy_instances layer_add_instance layer_has_instance layer_set_visible layer_get_visible layer_exists layer_x layer_y layer_get_x layer_get_y layer_hspeed layer_vspeed layer_get_hspeed layer_get_vspeed layer_script_begin layer_script_end layer_shader layer_get_script_begin layer_get_script_end layer_get_shader layer_set_target_room layer_get_target_room layer_reset_target_room layer_get_all layer_get_all_elements layer_get_name layer_depth layer_get_element_layer layer_get_element_type layer_element_move layer_force_draw_depth layer_is_draw_depth_forced layer_get_forced_depth layer_background_get_id layer_background_exists layer_background_create layer_background_destroy layer_background_visible layer_background_change layer_background_sprite layer_background_htiled layer_background_vtiled layer_background_stretch layer_background_yscale layer_background_xscale layer_background_blend layer_background_alpha layer_background_index layer_background_speed layer_background_get_visible layer_background_get_sprite layer_background_get_htiled layer_background_get_vtiled layer_background_get_stretch layer_background_get_yscale layer_background_get_xscale layer_background_get_blend layer_background_get_alpha layer_background_get_index layer_background_get_speed layer_sprite_get_id layer_sprite_exists layer_sprite_create layer_sprite_destroy layer_sprite_change layer_sprite_index layer_sprite_speed layer_sprite_xscale layer_sprite_yscale layer_sprite_angle layer_sprite_blend layer_sprite_alpha layer_sprite_x layer_sprite_y layer_sprite_get_sprite layer_sprite_get_index layer_sprite_get_speed layer_sprite_get_xscale layer_sprite_get_yscale layer_sprite_get_angle layer_sprite_get_blend layer_sprite_get_alpha layer_sprite_get_x layer_sprite_get_y layer_tilemap_get_id layer_tilemap_exists layer_tilemap_create layer_tilemap_destroy tilemap_tileset tilemap_x tilemap_y tilemap_set tilemap_set_at_pixel tilemap_get_tileset tilemap_get_tile_width tilemap_get_tile_height tilemap_get_width tilemap_get_height tilemap_get_x tilemap_get_y tilemap_get tilemap_get_at_pixel tilemap_get_cell_x_at_pixel tilemap_get_cell_y_at_pixel tilemap_clear draw_tilemap draw_tile tilemap_set_global_mask tilemap_get_global_mask tilemap_set_mask tilemap_get_mask tilemap_get_frame tile_set_empty tile_set_index tile_set_flip tile_set_mirror tile_set_rotate tile_get_empty tile_get_index tile_get_flip tile_get_mirror tile_get_rotate layer_tile_exists layer_tile_create layer_tile_destroy layer_tile_change layer_tile_xscale layer_tile_yscale layer_tile_blend layer_tile_alpha layer_tile_x layer_tile_y layer_tile_region layer_tile_visible layer_tile_get_sprite layer_tile_get_xscale layer_tile_get_yscale layer_tile_get_blend layer_tile_get_alpha layer_tile_get_x layer_tile_get_y layer_tile_get_region layer_tile_get_visible layer_instance_get_instance instance_activate_layer instance_deactivate_layer camera_create camera_create_view camera_destroy camera_apply camera_get_active camera_get_default camera_set_default camera_set_view_mat camera_set_proj_mat camera_set_update_script camera_set_begin_script camera_set_end_script camera_set_view_pos camera_set_view_size camera_set_view_speed camera_set_view_border camera_set_view_angle camera_set_view_target camera_get_view_mat camera_get_proj_mat camera_get_update_script camera_get_begin_script camera_get_end_script camera_get_view_x camera_get_view_y camera_get_view_width camera_get_view_height camera_get_view_speed_x camera_get_view_speed_y camera_get_view_border_x camera_get_view_border_y camera_get_view_angle camera_get_view_target view_get_camera view_get_visible view_get_xport view_get_yport view_get_wport view_get_hport view_get_surface_id view_set_camera view_set_visible view_set_xport view_set_yport view_set_wport view_set_hport view_set_surface_id gesture_drag_time gesture_drag_distance gesture_flick_speed gesture_double_tap_time gesture_double_tap_distance gesture_pinch_distance gesture_pinch_angle_towards gesture_pinch_angle_away gesture_rotate_time gesture_rotate_angle gesture_tap_count gesture_get_drag_time gesture_get_drag_distance gesture_get_flick_speed gesture_get_double_tap_time gesture_get_double_tap_distance gesture_get_pinch_distance gesture_get_pinch_angle_towards gesture_get_pinch_angle_away gesture_get_rotate_time gesture_get_rotate_angle gesture_get_tap_count keyboard_virtual_show keyboard_virtual_hide keyboard_virtual_status keyboard_virtual_height",
+literal:"true false"},illegal:'"',contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.C_NUMBER_MODE,{className:"meta",begin:"#",end:"$"}]}});b.registerLanguage("gml",function(a){return{aliases:["gml","GML"],case_insensitive:!1,keywords:{keyword:"begin end if then else while do for break continue with until repeat exit and or xor not return mod div switch case default var globalvar enum #macro #region #endregion",built_in:"is_real is_string is_array is_undefined is_int32 is_int64 is_ptr is_vec3 is_vec4 is_matrix is_bool typeof variable_global_exists variable_global_get variable_global_set variable_instance_exists variable_instance_get variable_instance_set variable_instance_get_names array_length_1d array_length_2d array_height_2d array_equals array_create array_copy random random_range irandom irandom_range random_set_seed random_get_seed randomize randomise choose abs round floor ceil sign frac sqrt sqr exp ln log2 log10 sin cos tan arcsin arccos arctan arctan2 dsin dcos dtan darcsin darccos darctan darctan2 degtorad radtodeg power logn min max mean median clamp lerp dot_product dot_product_3d dot_product_normalised dot_product_3d_normalised dot_product_normalized dot_product_3d_normalized math_set_epsilon math_get_epsilon angle_difference point_distance_3d point_distance point_direction lengthdir_x lengthdir_y real string int64 ptr string_format chr ansi_char ord string_length string_byte_length string_pos string_copy string_char_at string_ord_at string_byte_at string_set_byte_at string_delete string_insert string_lower string_upper string_repeat string_letters string_digits string_lettersdigits string_replace string_replace_all string_count string_hash_to_newline clipboard_has_text clipboard_set_text clipboard_get_text date_current_datetime date_create_datetime date_valid_datetime date_inc_year date_inc_month date_inc_week date_inc_day date_inc_hour date_inc_minute date_inc_second date_get_year date_get_month date_get_week date_get_day date_get_hour date_get_minute date_get_second date_get_weekday date_get_day_of_year date_get_hour_of_year date_get_minute_of_year date_get_second_of_year date_year_span date_month_span date_week_span date_day_span date_hour_span date_minute_span date_second_span date_compare_datetime date_compare_date date_compare_time date_date_of date_time_of date_datetime_string date_date_string date_time_string date_days_in_month date_days_in_year date_leap_year date_is_today date_set_timezone date_get_timezone game_set_speed game_get_speed motion_set motion_add place_free place_empty place_meeting place_snapped move_random move_snap move_towards_point move_contact_solid move_contact_all move_outside_solid move_outside_all move_bounce_solid move_bounce_all move_wrap distance_to_point distance_to_object position_empty position_meeting path_start path_end mp_linear_step mp_potential_step mp_linear_step_object mp_potential_step_object mp_potential_settings mp_linear_path mp_potential_path mp_linear_path_object mp_potential_path_object mp_grid_create mp_grid_destroy mp_grid_clear_all mp_grid_clear_cell mp_grid_clear_rectangle mp_grid_add_cell mp_grid_get_cell mp_grid_add_rectangle mp_grid_add_instances mp_grid_path mp_grid_draw mp_grid_to_ds_grid collision_point collision_rectangle collision_circle collision_ellipse collision_line collision_point_list collision_rectangle_list collision_circle_list collision_ellipse_list collision_line_list instance_position_list instance_place_list point_in_rectangle point_in_triangle point_in_circle rectangle_in_rectangle rectangle_in_triangle rectangle_in_circle instance_find instance_exists instance_number instance_position instance_nearest instance_furthest instance_place instance_create_depth instance_create_layer instance_copy instance_change instance_destroy position_destroy position_change instance_id_get instance_deactivate_all instance_deactivate_object instance_deactivate_region instance_activate_all instance_activate_object instance_activate_region room_goto room_goto_previous room_goto_next room_previous room_next room_restart game_end game_restart game_load game_save game_save_buffer game_load_buffer event_perform event_user event_perform_object event_inherited show_debug_message show_debug_overlay debug_event debug_get_callstack alarm_get alarm_set font_texture_page_size keyboard_set_map keyboard_get_map keyboard_unset_map keyboard_check keyboard_check_pressed keyboard_check_released keyboard_check_direct keyboard_get_numlock keyboard_set_numlock keyboard_key_press keyboard_key_release keyboard_clear io_clear mouse_check_button mouse_check_button_pressed mouse_check_button_released mouse_wheel_up mouse_wheel_down mouse_clear draw_self draw_sprite draw_sprite_pos draw_sprite_ext draw_sprite_stretched draw_sprite_stretched_ext draw_sprite_tiled draw_sprite_tiled_ext draw_sprite_part draw_sprite_part_ext draw_sprite_general draw_clear draw_clear_alpha draw_point draw_line draw_line_width draw_rectangle draw_roundrect draw_roundrect_ext draw_triangle draw_circle draw_ellipse draw_set_circle_precision draw_arrow draw_button draw_path draw_healthbar draw_getpixel draw_getpixel_ext draw_set_colour draw_set_color draw_set_alpha draw_get_colour draw_get_color draw_get_alpha merge_colour make_colour_rgb make_colour_hsv colour_get_red colour_get_green colour_get_blue colour_get_hue colour_get_saturation colour_get_value merge_color make_color_rgb make_color_hsv color_get_red color_get_green color_get_blue color_get_hue color_get_saturation color_get_value merge_color screen_save screen_save_part draw_set_font draw_set_halign draw_set_valign draw_text draw_text_ext string_width string_height string_width_ext string_height_ext draw_text_transformed draw_text_ext_transformed draw_text_colour draw_text_ext_colour draw_text_transformed_colour draw_text_ext_transformed_colour draw_text_color draw_text_ext_color draw_text_transformed_color draw_text_ext_transformed_color draw_point_colour draw_line_colour draw_line_width_colour draw_rectangle_colour draw_roundrect_colour draw_roundrect_colour_ext draw_triangle_colour draw_circle_colour draw_ellipse_colour draw_point_color draw_line_color draw_line_width_color draw_rectangle_color draw_roundrect_color draw_roundrect_color_ext draw_triangle_color draw_circle_color draw_ellipse_color draw_primitive_begin draw_vertex draw_vertex_colour draw_vertex_color draw_primitive_end sprite_get_uvs font_get_uvs sprite_get_texture font_get_texture texture_get_width texture_get_height texture_get_uvs draw_primitive_begin_texture draw_vertex_texture draw_vertex_texture_colour draw_vertex_texture_color texture_global_scale surface_create surface_create_ext surface_resize surface_free surface_exists surface_get_width surface_get_height surface_get_texture surface_set_target surface_set_target_ext surface_reset_target surface_depth_disable surface_get_depth_disable draw_surface draw_surface_stretched draw_surface_tiled draw_surface_part draw_surface_ext draw_surface_stretched_ext draw_surface_tiled_ext draw_surface_part_ext draw_surface_general surface_getpixel surface_getpixel_ext surface_save surface_save_part surface_copy surface_copy_part application_surface_draw_enable application_get_position application_surface_enable application_surface_is_enabled display_get_width display_get_height display_get_orientation display_get_gui_width display_get_gui_height display_reset display_mouse_get_x display_mouse_get_y display_mouse_set display_set_ui_visibility window_set_fullscreen window_get_fullscreen window_set_caption window_set_min_width window_set_max_width window_set_min_height window_set_max_height window_get_visible_rects window_get_caption window_set_cursor window_get_cursor window_set_colour window_get_colour window_set_color window_get_color window_set_position window_set_size window_set_rectangle window_center window_get_x window_get_y window_get_width window_get_height window_mouse_get_x window_mouse_get_y window_mouse_set window_view_mouse_get_x window_view_mouse_get_y window_views_mouse_get_x window_views_mouse_get_y audio_listener_position audio_listener_velocity audio_listener_orientation audio_emitter_position audio_emitter_create audio_emitter_free audio_emitter_exists audio_emitter_pitch audio_emitter_velocity audio_emitter_falloff audio_emitter_gain audio_play_sound audio_play_sound_on audio_play_sound_at audio_stop_sound audio_resume_music audio_music_is_playing audio_resume_sound audio_pause_sound audio_pause_music audio_channel_num audio_sound_length audio_get_type audio_falloff_set_model audio_play_music audio_stop_music audio_master_gain audio_music_gain audio_sound_gain audio_sound_pitch audio_stop_all audio_resume_all audio_pause_all audio_is_playing audio_is_paused audio_exists audio_sound_set_track_position audio_sound_get_track_position audio_emitter_get_gain audio_emitter_get_pitch audio_emitter_get_x audio_emitter_get_y audio_emitter_get_z audio_emitter_get_vx audio_emitter_get_vy audio_emitter_get_vz audio_listener_set_position audio_listener_set_velocity audio_listener_set_orientation audio_listener_get_data audio_set_master_gain audio_get_master_gain audio_sound_get_gain audio_sound_get_pitch audio_get_name audio_sound_set_track_position audio_sound_get_track_position audio_create_stream audio_destroy_stream audio_create_sync_group audio_destroy_sync_group audio_play_in_sync_group audio_start_sync_group audio_stop_sync_group audio_pause_sync_group audio_resume_sync_group audio_sync_group_get_track_pos audio_sync_group_debug audio_sync_group_is_playing audio_debug audio_group_load audio_group_unload audio_group_is_loaded audio_group_load_progress audio_group_name audio_group_stop_all audio_group_set_gain audio_create_buffer_sound audio_free_buffer_sound audio_create_play_queue audio_free_play_queue audio_queue_sound audio_get_recorder_count audio_get_recorder_info audio_start_recording audio_stop_recording audio_sound_get_listener_mask audio_emitter_get_listener_mask audio_get_listener_mask audio_sound_set_listener_mask audio_emitter_set_listener_mask audio_set_listener_mask audio_get_listener_count audio_get_listener_info audio_system show_message show_message_async clickable_add clickable_add_ext clickable_change clickable_change_ext clickable_delete clickable_exists clickable_set_style show_question show_question_async get_integer get_string get_integer_async get_string_async get_login_async get_open_filename get_save_filename get_open_filename_ext get_save_filename_ext show_error highscore_clear highscore_add highscore_value highscore_name draw_highscore sprite_exists sprite_get_name sprite_get_number sprite_get_width sprite_get_height sprite_get_xoffset sprite_get_yoffset sprite_get_bbox_left sprite_get_bbox_right sprite_get_bbox_top sprite_get_bbox_bottom sprite_save sprite_save_strip sprite_set_cache_size sprite_set_cache_size_ext sprite_get_tpe sprite_prefetch sprite_prefetch_multi sprite_flush sprite_flush_multi sprite_set_speed sprite_get_speed_type sprite_get_speed font_exists font_get_name font_get_fontname font_get_bold font_get_italic font_get_first font_get_last font_get_size font_set_cache_size path_exists path_get_name path_get_length path_get_time path_get_kind path_get_closed path_get_precision path_get_number path_get_point_x path_get_point_y path_get_point_speed path_get_x path_get_y path_get_speed script_exists script_get_name timeline_add timeline_delete timeline_clear timeline_exists timeline_get_name timeline_moment_clear timeline_moment_add_script timeline_size timeline_max_moment object_exists object_get_name object_get_sprite object_get_solid object_get_visible object_get_persistent object_get_mask object_get_parent object_get_physics object_is_ancestor room_exists room_get_name sprite_set_offset sprite_duplicate sprite_assign sprite_merge sprite_add sprite_replace sprite_create_from_surface sprite_add_from_surface sprite_delete sprite_set_alpha_from_sprite sprite_collision_mask font_add_enable_aa font_add_get_enable_aa font_add font_add_sprite font_add_sprite_ext font_replace font_replace_sprite font_replace_sprite_ext font_delete path_set_kind path_set_closed path_set_precision path_add path_assign path_duplicate path_append path_delete path_add_point path_insert_point path_change_point path_delete_point path_clear_points path_reverse path_mirror path_flip path_rotate path_rescale path_shift script_execute object_set_sprite object_set_solid object_set_visible object_set_persistent object_set_mask room_set_width room_set_height room_set_persistent room_set_background_colour room_set_background_color room_set_view room_set_viewport room_get_viewport room_set_view_enabled room_add room_duplicate room_assign room_instance_add room_instance_clear room_get_camera room_set_camera asset_get_index asset_get_type file_text_open_from_string file_text_open_read file_text_open_write file_text_open_append file_text_close file_text_write_string file_text_write_real file_text_writeln file_text_read_string file_text_read_real file_text_readln file_text_eof file_text_eoln file_exists file_delete file_rename file_copy directory_exists directory_create directory_destroy file_find_first file_find_next file_find_close file_attributes filename_name filename_path filename_dir filename_drive filename_ext filename_change_ext file_bin_open file_bin_rewrite file_bin_close file_bin_position file_bin_size file_bin_seek file_bin_write_byte file_bin_read_byte parameter_count parameter_string environment_get_variable ini_open_from_string ini_open ini_close ini_read_string ini_read_real ini_write_string ini_write_real ini_key_exists ini_section_exists ini_key_delete ini_section_delete ds_set_precision ds_exists ds_stack_create ds_stack_destroy ds_stack_clear ds_stack_copy ds_stack_size ds_stack_empty ds_stack_push ds_stack_pop ds_stack_top ds_stack_write ds_stack_read ds_queue_create ds_queue_destroy ds_queue_clear ds_queue_copy ds_queue_size ds_queue_empty ds_queue_enqueue ds_queue_dequeue ds_queue_head ds_queue_tail ds_queue_write ds_queue_read ds_list_create ds_list_destroy ds_list_clear ds_list_copy ds_list_size ds_list_empty ds_list_add ds_list_insert ds_list_replace ds_list_delete ds_list_find_index ds_list_find_value ds_list_mark_as_list ds_list_mark_as_map ds_list_sort ds_list_shuffle ds_list_write ds_list_read ds_list_set ds_map_create ds_map_destroy ds_map_clear ds_map_copy ds_map_size ds_map_empty ds_map_add ds_map_add_list ds_map_add_map ds_map_replace ds_map_replace_map ds_map_replace_list ds_map_delete ds_map_exists ds_map_find_value ds_map_find_previous ds_map_find_next ds_map_find_first ds_map_find_last ds_map_write ds_map_read ds_map_secure_save ds_map_secure_load ds_map_secure_load_buffer ds_map_secure_save_buffer ds_map_set ds_priority_create ds_priority_destroy ds_priority_clear ds_priority_copy ds_priority_size ds_priority_empty ds_priority_add ds_priority_change_priority ds_priority_find_priority ds_priority_delete_value ds_priority_delete_min ds_priority_find_min ds_priority_delete_max ds_priority_find_max ds_priority_write ds_priority_read ds_grid_create ds_grid_destroy ds_grid_copy ds_grid_resize ds_grid_width ds_grid_height ds_grid_clear ds_grid_set ds_grid_add ds_grid_multiply ds_grid_set_region ds_grid_add_region ds_grid_multiply_region ds_grid_set_disk ds_grid_add_disk ds_grid_multiply_disk ds_grid_set_grid_region ds_grid_add_grid_region ds_grid_multiply_grid_region ds_grid_get ds_grid_get_sum ds_grid_get_max ds_grid_get_min ds_grid_get_mean ds_grid_get_disk_sum ds_grid_get_disk_min ds_grid_get_disk_max ds_grid_get_disk_mean ds_grid_value_exists ds_grid_value_x ds_grid_value_y ds_grid_value_disk_exists ds_grid_value_disk_x ds_grid_value_disk_y ds_grid_shuffle ds_grid_write ds_grid_read ds_grid_sort ds_grid_set ds_grid_get effect_create_below effect_create_above effect_clear part_type_create part_type_destroy part_type_exists part_type_clear part_type_shape part_type_sprite part_type_size part_type_scale part_type_orientation part_type_life part_type_step part_type_death part_type_speed part_type_direction part_type_gravity part_type_colour1 part_type_colour2 part_type_colour3 part_type_colour_mix part_type_colour_rgb part_type_colour_hsv part_type_color1 part_type_color2 part_type_color3 part_type_color_mix part_type_color_rgb part_type_color_hsv part_type_alpha1 part_type_alpha2 part_type_alpha3 part_type_blend part_system_create part_system_create_layer part_system_destroy part_system_exists part_system_clear part_system_draw_order part_system_depth part_system_position part_system_automatic_update part_system_automatic_draw part_system_update part_system_drawit part_system_get_layer part_system_layer part_particles_create part_particles_create_colour part_particles_create_color part_particles_clear part_particles_count part_emitter_create part_emitter_destroy part_emitter_destroy_all part_emitter_exists part_emitter_clear part_emitter_region part_emitter_burst part_emitter_stream external_call external_define external_free window_handle window_device matrix_get matrix_set matrix_build_identity matrix_build matrix_build_lookat matrix_build_projection_ortho matrix_build_projection_perspective matrix_build_projection_perspective_fov matrix_multiply matrix_transform_vertex matrix_stack_push matrix_stack_pop matrix_stack_multiply matrix_stack_set matrix_stack_clear matrix_stack_top matrix_stack_is_empty browser_input_capture os_get_config os_get_info os_get_language os_get_region os_lock_orientation display_get_dpi_x display_get_dpi_y display_set_gui_size display_set_gui_maximise display_set_gui_maximize device_mouse_dbclick_enable display_set_timing_method display_get_timing_method display_set_sleep_margin display_get_sleep_margin virtual_key_add virtual_key_hide virtual_key_delete virtual_key_show draw_enable_drawevent draw_enable_swf_aa draw_set_swf_aa_level draw_get_swf_aa_level draw_texture_flush draw_flush gpu_set_blendenable gpu_set_ztestenable gpu_set_zfunc gpu_set_zwriteenable gpu_set_lightingenable gpu_set_fog gpu_set_cullmode gpu_set_blendmode gpu_set_blendmode_ext gpu_set_blendmode_ext_sepalpha gpu_set_colorwriteenable gpu_set_colourwriteenable gpu_set_alphatestenable gpu_set_alphatestref gpu_set_alphatestfunc gpu_set_texfilter gpu_set_texfilter_ext gpu_set_texrepeat gpu_set_texrepeat_ext gpu_set_tex_filter gpu_set_tex_filter_ext gpu_set_tex_repeat gpu_set_tex_repeat_ext gpu_set_tex_mip_filter gpu_set_tex_mip_filter_ext gpu_set_tex_mip_bias gpu_set_tex_mip_bias_ext gpu_set_tex_min_mip gpu_set_tex_min_mip_ext gpu_set_tex_max_mip gpu_set_tex_max_mip_ext gpu_set_tex_max_aniso gpu_set_tex_max_aniso_ext gpu_set_tex_mip_enable gpu_set_tex_mip_enable_ext gpu_get_blendenable gpu_get_ztestenable gpu_get_zfunc gpu_get_zwriteenable gpu_get_lightingenable gpu_get_fog gpu_get_cullmode gpu_get_blendmode gpu_get_blendmode_ext gpu_get_blendmode_ext_sepalpha gpu_get_blendmode_src gpu_get_blendmode_dest gpu_get_blendmode_srcalpha gpu_get_blendmode_destalpha gpu_get_colorwriteenable gpu_get_colourwriteenable gpu_get_alphatestenable gpu_get_alphatestref gpu_get_alphatestfunc gpu_get_texfilter gpu_get_texfilter_ext gpu_get_texrepeat gpu_get_texrepeat_ext gpu_get_tex_filter gpu_get_tex_filter_ext gpu_get_tex_repeat gpu_get_tex_repeat_ext gpu_get_tex_mip_filter gpu_get_tex_mip_filter_ext gpu_get_tex_mip_bias gpu_get_tex_mip_bias_ext gpu_get_tex_min_mip gpu_get_tex_min_mip_ext gpu_get_tex_max_mip gpu_get_tex_max_mip_ext gpu_get_tex_max_aniso gpu_get_tex_max_aniso_ext gpu_get_tex_mip_enable gpu_get_tex_mip_enable_ext gpu_push_state gpu_pop_state gpu_get_state gpu_set_state draw_light_define_ambient draw_light_define_direction draw_light_define_point draw_light_enable draw_set_lighting draw_light_get_ambient draw_light_get draw_get_lighting shop_leave_rating url_get_domain url_open url_open_ext url_open_full get_timer achievement_login achievement_logout achievement_post achievement_increment achievement_post_score achievement_available achievement_show_achievements achievement_show_leaderboards achievement_load_friends achievement_load_leaderboard achievement_send_challenge achievement_load_progress achievement_reset achievement_login_status achievement_get_pic achievement_show_challenge_notifications achievement_get_challenges achievement_event achievement_show achievement_get_info cloud_file_save cloud_string_save cloud_synchronise ads_enable ads_disable ads_setup ads_engagement_launch ads_engagement_available ads_engagement_active ads_event ads_event_preload ads_set_reward_callback ads_get_display_height ads_get_display_width ads_move ads_interstitial_available ads_interstitial_display device_get_tilt_x device_get_tilt_y device_get_tilt_z device_is_keypad_open device_mouse_check_button device_mouse_check_button_pressed device_mouse_check_button_released device_mouse_x device_mouse_y device_mouse_raw_x device_mouse_raw_y device_mouse_x_to_gui device_mouse_y_to_gui iap_activate iap_status iap_enumerate_products iap_restore_all iap_acquire iap_consume iap_product_details iap_purchase_details facebook_init facebook_login facebook_status facebook_graph_request facebook_dialog facebook_logout facebook_launch_offerwall facebook_post_message facebook_send_invite facebook_user_id facebook_accesstoken facebook_check_permission facebook_request_read_permissions facebook_request_publish_permissions gamepad_is_supported gamepad_get_device_count gamepad_is_connected gamepad_get_description gamepad_get_button_threshold gamepad_set_button_threshold gamepad_get_axis_deadzone gamepad_set_axis_deadzone gamepad_button_count gamepad_button_check gamepad_button_check_pressed gamepad_button_check_released gamepad_button_value gamepad_axis_count gamepad_axis_value gamepad_set_vibration gamepad_set_colour gamepad_set_color os_is_paused window_has_focus code_is_compiled http_get http_get_file http_post_string http_request json_encode json_decode zip_unzip load_csv base64_encode base64_decode md5_string_unicode md5_string_utf8 md5_file os_is_network_connected sha1_string_unicode sha1_string_utf8 sha1_file os_powersave_enable analytics_event analytics_event_ext win8_livetile_tile_notification win8_livetile_tile_clear win8_livetile_badge_notification win8_livetile_badge_clear win8_livetile_queue_enable win8_secondarytile_pin win8_secondarytile_badge_notification win8_secondarytile_delete win8_livetile_notification_begin win8_livetile_notification_secondary_begin win8_livetile_notification_expiry win8_livetile_notification_tag win8_livetile_notification_text_add win8_livetile_notification_image_add win8_livetile_notification_end win8_appbar_enable win8_appbar_add_element win8_appbar_remove_element win8_settingscharm_add_entry win8_settingscharm_add_html_entry win8_settingscharm_add_xaml_entry win8_settingscharm_set_xaml_property win8_settingscharm_get_xaml_property win8_settingscharm_remove_entry win8_share_image win8_share_screenshot win8_share_file win8_share_url win8_share_text win8_search_enable win8_search_disable win8_search_add_suggestions win8_device_touchscreen_available win8_license_initialize_sandbox win8_license_trial_version winphone_license_trial_version winphone_tile_title winphone_tile_count winphone_tile_back_title winphone_tile_back_content winphone_tile_back_content_wide winphone_tile_front_image winphone_tile_front_image_small winphone_tile_front_image_wide winphone_tile_back_image winphone_tile_back_image_wide winphone_tile_background_colour winphone_tile_background_color winphone_tile_icon_image winphone_tile_small_icon_image winphone_tile_wide_content winphone_tile_cycle_images winphone_tile_small_background_image physics_world_create physics_world_gravity physics_world_update_speed physics_world_update_iterations physics_world_draw_debug physics_pause_enable physics_fixture_create physics_fixture_set_kinematic physics_fixture_set_density physics_fixture_set_awake physics_fixture_set_restitution physics_fixture_set_friction physics_fixture_set_collision_group physics_fixture_set_sensor physics_fixture_set_linear_damping physics_fixture_set_angular_damping physics_fixture_set_circle_shape physics_fixture_set_box_shape physics_fixture_set_edge_shape physics_fixture_set_polygon_shape physics_fixture_set_chain_shape physics_fixture_add_point physics_fixture_bind physics_fixture_bind_ext physics_fixture_delete physics_apply_force physics_apply_impulse physics_apply_angular_impulse physics_apply_local_force physics_apply_local_impulse physics_apply_torque physics_mass_properties physics_draw_debug physics_test_overlap physics_remove_fixture physics_set_friction physics_set_density physics_set_restitution physics_get_friction physics_get_density physics_get_restitution physics_joint_distance_create physics_joint_rope_create physics_joint_revolute_create physics_joint_prismatic_create physics_joint_pulley_create physics_joint_wheel_create physics_joint_weld_create physics_joint_friction_create physics_joint_gear_create physics_joint_enable_motor physics_joint_get_value physics_joint_set_value physics_joint_delete physics_particle_create physics_particle_delete physics_particle_delete_region_circle physics_particle_delete_region_box physics_particle_delete_region_poly physics_particle_set_flags physics_particle_set_category_flags physics_particle_draw physics_particle_draw_ext physics_particle_count physics_particle_get_data physics_particle_get_data_particle physics_particle_group_begin physics_particle_group_circle physics_particle_group_box physics_particle_group_polygon physics_particle_group_add_point physics_particle_group_end physics_particle_group_join physics_particle_group_delete physics_particle_group_count physics_particle_group_get_data physics_particle_group_get_mass physics_particle_group_get_inertia physics_particle_group_get_centre_x physics_particle_group_get_centre_y physics_particle_group_get_vel_x physics_particle_group_get_vel_y physics_particle_group_get_ang_vel physics_particle_group_get_x physics_particle_group_get_y physics_particle_group_get_angle physics_particle_set_group_flags physics_particle_get_group_flags physics_particle_get_max_count physics_particle_get_radius physics_particle_get_density physics_particle_get_damping physics_particle_get_gravity_scale physics_particle_set_max_count physics_particle_set_radius physics_particle_set_density physics_particle_set_damping physics_particle_set_gravity_scale network_create_socket network_create_socket_ext network_create_server network_create_server_raw network_connect network_connect_raw network_send_packet network_send_raw network_send_broadcast network_send_udp network_send_udp_raw network_set_timeout network_set_config network_resolve network_destroy buffer_create buffer_write buffer_read buffer_seek buffer_get_surface buffer_set_surface buffer_delete buffer_exists buffer_get_type buffer_get_alignment buffer_poke buffer_peek buffer_save buffer_save_ext buffer_load buffer_load_ext buffer_load_partial buffer_copy buffer_fill buffer_get_size buffer_tell buffer_resize buffer_md5 buffer_sha1 buffer_base64_encode buffer_base64_decode buffer_base64_decode_ext buffer_sizeof buffer_get_address buffer_create_from_vertex_buffer buffer_create_from_vertex_buffer_ext buffer_copy_from_vertex_buffer buffer_async_group_begin buffer_async_group_option buffer_async_group_end buffer_load_async buffer_save_async gml_release_mode gml_pragma steam_activate_overlay steam_is_overlay_enabled steam_is_overlay_activated steam_get_persona_name steam_initialised steam_is_cloud_enabled_for_app steam_is_cloud_enabled_for_account steam_file_persisted steam_get_quota_total steam_get_quota_free steam_file_write steam_file_write_file steam_file_read steam_file_delete steam_file_exists steam_file_size steam_file_share steam_is_screenshot_requested steam_send_screenshot steam_is_user_logged_on steam_get_user_steam_id steam_user_owns_dlc steam_user_installed_dlc steam_set_achievement steam_get_achievement steam_clear_achievement steam_set_stat_int steam_set_stat_float steam_set_stat_avg_rate steam_get_stat_int steam_get_stat_float steam_get_stat_avg_rate steam_reset_all_stats steam_reset_all_stats_achievements steam_stats_ready steam_create_leaderboard steam_upload_score steam_upload_score_ext steam_download_scores_around_user steam_download_scores steam_download_friends_scores steam_upload_score_buffer steam_upload_score_buffer_ext steam_current_game_language steam_available_languages steam_activate_overlay_browser steam_activate_overlay_user steam_activate_overlay_store steam_get_user_persona_name steam_get_app_id steam_get_user_account_id steam_ugc_download steam_ugc_create_item steam_ugc_start_item_update steam_ugc_set_item_title steam_ugc_set_item_description steam_ugc_set_item_visibility steam_ugc_set_item_tags steam_ugc_set_item_content steam_ugc_set_item_preview steam_ugc_submit_item_update steam_ugc_get_item_update_progress steam_ugc_subscribe_item steam_ugc_unsubscribe_item steam_ugc_num_subscribed_items steam_ugc_get_subscribed_items steam_ugc_get_item_install_info steam_ugc_get_item_update_info steam_ugc_request_item_details steam_ugc_create_query_user steam_ugc_create_query_user_ex steam_ugc_create_query_all steam_ugc_create_query_all_ex steam_ugc_query_set_cloud_filename_filter steam_ugc_query_set_match_any_tag steam_ugc_query_set_search_text steam_ugc_query_set_ranked_by_trend_days steam_ugc_query_add_required_tag steam_ugc_query_add_excluded_tag steam_ugc_query_set_return_long_description steam_ugc_query_set_return_total_only steam_ugc_query_set_allow_cached_response steam_ugc_send_query shader_set shader_get_name shader_reset shader_current shader_is_compiled shader_get_sampler_index shader_get_uniform shader_set_uniform_i shader_set_uniform_i_array shader_set_uniform_f shader_set_uniform_f_array shader_set_uniform_matrix shader_set_uniform_matrix_array shader_enable_corner_id texture_set_stage texture_get_texel_width texture_get_texel_height shaders_are_supported vertex_format_begin vertex_format_end vertex_format_delete vertex_format_add_position vertex_format_add_position_3d vertex_format_add_colour vertex_format_add_color vertex_format_add_normal vertex_format_add_texcoord vertex_format_add_textcoord vertex_format_add_custom vertex_create_buffer vertex_create_buffer_ext vertex_delete_buffer vertex_begin vertex_end vertex_position vertex_position_3d vertex_colour vertex_color vertex_argb vertex_texcoord vertex_normal vertex_float1 vertex_float2 vertex_float3 vertex_float4 vertex_ubyte4 vertex_submit vertex_freeze vertex_get_number vertex_get_buffer_size vertex_create_buffer_from_buffer vertex_create_buffer_from_buffer_ext push_local_notification push_get_first_local_notification push_get_next_local_notification push_cancel_local_notification skeleton_animation_set skeleton_animation_get skeleton_animation_mix skeleton_animation_set_ext skeleton_animation_get_ext skeleton_animation_get_duration skeleton_animation_get_frames skeleton_animation_clear skeleton_skin_set skeleton_skin_get skeleton_attachment_set skeleton_attachment_get skeleton_attachment_create skeleton_collision_draw_set skeleton_bone_data_get skeleton_bone_data_set skeleton_bone_state_get skeleton_bone_state_set skeleton_get_minmax skeleton_get_num_bounds skeleton_get_bounds skeleton_animation_get_frame skeleton_animation_set_frame draw_skeleton draw_skeleton_time draw_skeleton_instance draw_skeleton_collision skeleton_animation_list skeleton_skin_list skeleton_slot_data layer_get_id layer_get_id_at_depth layer_get_depth layer_create layer_destroy layer_destroy_instances layer_add_instance layer_has_instance layer_set_visible layer_get_visible layer_exists layer_x layer_y layer_get_x layer_get_y layer_hspeed layer_vspeed layer_get_hspeed layer_get_vspeed layer_script_begin layer_script_end layer_shader layer_get_script_begin layer_get_script_end layer_get_shader layer_set_target_room layer_get_target_room layer_reset_target_room layer_get_all layer_get_all_elements layer_get_name layer_depth layer_get_element_layer layer_get_element_type layer_element_move layer_force_draw_depth layer_is_draw_depth_forced layer_get_forced_depth layer_background_get_id layer_background_exists layer_background_create layer_background_destroy layer_background_visible layer_background_change layer_background_sprite layer_background_htiled layer_background_vtiled layer_background_stretch layer_background_yscale layer_background_xscale layer_background_blend layer_background_alpha layer_background_index layer_background_speed layer_background_get_visible layer_background_get_sprite layer_background_get_htiled layer_background_get_vtiled layer_background_get_stretch layer_background_get_yscale layer_background_get_xscale layer_background_get_blend layer_background_get_alpha layer_background_get_index layer_background_get_speed layer_sprite_get_id layer_sprite_exists layer_sprite_create layer_sprite_destroy layer_sprite_change layer_sprite_index layer_sprite_speed layer_sprite_xscale layer_sprite_yscale layer_sprite_angle layer_sprite_blend layer_sprite_alpha layer_sprite_x layer_sprite_y layer_sprite_get_sprite layer_sprite_get_index layer_sprite_get_speed layer_sprite_get_xscale layer_sprite_get_yscale layer_sprite_get_angle layer_sprite_get_blend layer_sprite_get_alpha layer_sprite_get_x layer_sprite_get_y layer_tilemap_get_id layer_tilemap_exists layer_tilemap_create layer_tilemap_destroy tilemap_tileset tilemap_x tilemap_y tilemap_set tilemap_set_at_pixel tilemap_get_tileset tilemap_get_tile_width tilemap_get_tile_height tilemap_get_width tilemap_get_height tilemap_get_x tilemap_get_y tilemap_get tilemap_get_at_pixel tilemap_get_cell_x_at_pixel tilemap_get_cell_y_at_pixel tilemap_clear draw_tilemap draw_tile tilemap_set_global_mask tilemap_get_global_mask tilemap_set_mask tilemap_get_mask tilemap_get_frame tile_set_empty tile_set_index tile_set_flip tile_set_mirror tile_set_rotate tile_get_empty tile_get_index tile_get_flip tile_get_mirror tile_get_rotate layer_tile_exists layer_tile_create layer_tile_destroy layer_tile_change layer_tile_xscale layer_tile_yscale layer_tile_blend layer_tile_alpha layer_tile_x layer_tile_y layer_tile_region layer_tile_visible layer_tile_get_sprite layer_tile_get_xscale layer_tile_get_yscale layer_tile_get_blend layer_tile_get_alpha layer_tile_get_x layer_tile_get_y layer_tile_get_region layer_tile_get_visible layer_instance_get_instance instance_activate_layer instance_deactivate_layer camera_create camera_create_view camera_destroy camera_apply camera_get_active camera_get_default camera_set_default camera_set_view_mat camera_set_proj_mat camera_set_update_script camera_set_begin_script camera_set_end_script camera_set_view_pos camera_set_view_size camera_set_view_speed camera_set_view_border camera_set_view_angle camera_set_view_target camera_get_view_mat camera_get_proj_mat camera_get_update_script camera_get_begin_script camera_get_end_script camera_get_view_x camera_get_view_y camera_get_view_width camera_get_view_height camera_get_view_speed_x camera_get_view_speed_y camera_get_view_border_x camera_get_view_border_y camera_get_view_angle camera_get_view_target view_get_camera view_get_visible view_get_xport view_get_yport view_get_wport view_get_hport view_get_surface_id view_set_camera view_set_visible view_set_xport view_set_yport view_set_wport view_set_hport view_set_surface_id gesture_drag_time gesture_drag_distance gesture_flick_speed gesture_double_tap_time gesture_double_tap_distance gesture_pinch_distance gesture_pinch_angle_towards gesture_pinch_angle_away gesture_rotate_time gesture_rotate_angle gesture_tap_count gesture_get_drag_time gesture_get_drag_distance gesture_get_flick_speed gesture_get_double_tap_time gesture_get_double_tap_distance gesture_get_pinch_distance gesture_get_pinch_angle_towards gesture_get_pinch_angle_away gesture_get_rotate_time gesture_get_rotate_angle gesture_get_tap_count keyboard_virtual_show keyboard_virtual_hide keyboard_virtual_status keyboard_virtual_height",
 literal:"self other all noone global local undefined pointer_invalid pointer_null path_action_stop path_action_restart path_action_continue path_action_reverse true false pi GM_build_date GM_version GM_runtime_version  timezone_local timezone_utc gamespeed_fps gamespeed_microseconds  ev_create ev_destroy ev_step ev_alarm ev_keyboard ev_mouse ev_collision ev_other ev_draw ev_draw_begin ev_draw_end ev_draw_pre ev_draw_post ev_keypress ev_keyrelease ev_trigger ev_left_button ev_right_button ev_middle_button ev_no_button ev_left_press ev_right_press ev_middle_press ev_left_release ev_right_release ev_middle_release ev_mouse_enter ev_mouse_leave ev_mouse_wheel_up ev_mouse_wheel_down ev_global_left_button ev_global_right_button ev_global_middle_button ev_global_left_press ev_global_right_press ev_global_middle_press ev_global_left_release ev_global_right_release ev_global_middle_release ev_joystick1_left ev_joystick1_right ev_joystick1_up ev_joystick1_down ev_joystick1_button1 ev_joystick1_button2 ev_joystick1_button3 ev_joystick1_button4 ev_joystick1_button5 ev_joystick1_button6 ev_joystick1_button7 ev_joystick1_button8 ev_joystick2_left ev_joystick2_right ev_joystick2_up ev_joystick2_down ev_joystick2_button1 ev_joystick2_button2 ev_joystick2_button3 ev_joystick2_button4 ev_joystick2_button5 ev_joystick2_button6 ev_joystick2_button7 ev_joystick2_button8 ev_outside ev_boundary ev_game_start ev_game_end ev_room_start ev_room_end ev_no_more_lives ev_animation_end ev_end_of_path ev_no_more_health ev_close_button ev_user0 ev_user1 ev_user2 ev_user3 ev_user4 ev_user5 ev_user6 ev_user7 ev_user8 ev_user9 ev_user10 ev_user11 ev_user12 ev_user13 ev_user14 ev_user15 ev_step_normal ev_step_begin ev_step_end ev_gui ev_gui_begin ev_gui_end ev_cleanup ev_gesture ev_gesture_tap ev_gesture_double_tap ev_gesture_drag_start ev_gesture_dragging ev_gesture_drag_end ev_gesture_flick ev_gesture_pinch_start ev_gesture_pinch_in ev_gesture_pinch_out ev_gesture_pinch_end ev_gesture_rotate_start ev_gesture_rotating ev_gesture_rotate_end ev_global_gesture_tap ev_global_gesture_double_tap ev_global_gesture_drag_start ev_global_gesture_dragging ev_global_gesture_drag_end ev_global_gesture_flick ev_global_gesture_pinch_start ev_global_gesture_pinch_in ev_global_gesture_pinch_out ev_global_gesture_pinch_end ev_global_gesture_rotate_start ev_global_gesture_rotating ev_global_gesture_rotate_end vk_nokey vk_anykey vk_enter vk_return vk_shift vk_control vk_alt vk_escape vk_space vk_backspace vk_tab vk_pause vk_printscreen vk_left vk_right vk_up vk_down vk_home vk_end vk_delete vk_insert vk_pageup vk_pagedown vk_f1 vk_f2 vk_f3 vk_f4 vk_f5 vk_f6 vk_f7 vk_f8 vk_f9 vk_f10 vk_f11 vk_f12 vk_numpad0 vk_numpad1 vk_numpad2 vk_numpad3 vk_numpad4 vk_numpad5 vk_numpad6 vk_numpad7 vk_numpad8 vk_numpad9 vk_divide vk_multiply vk_subtract vk_add vk_decimal vk_lshift vk_lcontrol vk_lalt vk_rshift vk_rcontrol vk_ralt  mb_any mb_none mb_left mb_right mb_middle c_aqua c_black c_blue c_dkgray c_fuchsia c_gray c_green c_lime c_ltgray c_maroon c_navy c_olive c_purple c_red c_silver c_teal c_white c_yellow c_orange fa_left fa_center fa_right fa_top fa_middle fa_bottom pr_pointlist pr_linelist pr_linestrip pr_trianglelist pr_trianglestrip pr_trianglefan bm_complex bm_normal bm_add bm_max bm_subtract bm_zero bm_one bm_src_colour bm_inv_src_colour bm_src_color bm_inv_src_color bm_src_alpha bm_inv_src_alpha bm_dest_alpha bm_inv_dest_alpha bm_dest_colour bm_inv_dest_colour bm_dest_color bm_inv_dest_color bm_src_alpha_sat tf_point tf_linear tf_anisotropic mip_off mip_on mip_markedonly audio_falloff_none audio_falloff_inverse_distance audio_falloff_inverse_distance_clamped audio_falloff_linear_distance audio_falloff_linear_distance_clamped audio_falloff_exponent_distance audio_falloff_exponent_distance_clamped audio_old_system audio_new_system audio_mono audio_stereo audio_3d cr_default cr_none cr_arrow cr_cross cr_beam cr_size_nesw cr_size_ns cr_size_nwse cr_size_we cr_uparrow cr_hourglass cr_drag cr_appstart cr_handpoint cr_size_all spritespeed_framespersecond spritespeed_framespergameframe asset_object asset_unknown asset_sprite asset_sound asset_room asset_path asset_script asset_font asset_timeline asset_tiles asset_shader fa_readonly fa_hidden fa_sysfile fa_volumeid fa_directory fa_archive  ds_type_map ds_type_list ds_type_stack ds_type_queue ds_type_grid ds_type_priority ef_explosion ef_ring ef_ellipse ef_firework ef_smoke ef_smokeup ef_star ef_spark ef_flare ef_cloud ef_rain ef_snow pt_shape_pixel pt_shape_disk pt_shape_square pt_shape_line pt_shape_star pt_shape_circle pt_shape_ring pt_shape_sphere pt_shape_flare pt_shape_spark pt_shape_explosion pt_shape_cloud pt_shape_smoke pt_shape_snow ps_distr_linear ps_distr_gaussian ps_distr_invgaussian ps_shape_rectangle ps_shape_ellipse ps_shape_diamond ps_shape_line ty_real ty_string dll_cdecl dll_stdcall matrix_view matrix_projection matrix_world os_win32 os_windows os_macosx os_ios os_android os_symbian os_linux os_unknown os_winphone os_tizen os_win8native os_wiiu os_3ds  os_psvita os_bb10 os_ps4 os_xboxone os_ps3 os_xbox360 os_uwp os_tvos os_switch browser_not_a_browser browser_unknown browser_ie browser_firefox browser_chrome browser_safari browser_safari_mobile browser_opera browser_tizen browser_edge browser_windows_store browser_ie_mobile  device_ios_unknown device_ios_iphone device_ios_iphone_retina device_ios_ipad device_ios_ipad_retina device_ios_iphone5 device_ios_iphone6 device_ios_iphone6plus device_emulator device_tablet display_landscape display_landscape_flipped display_portrait display_portrait_flipped tm_sleep tm_countvsyncs of_challenge_win of_challen ge_lose of_challenge_tie leaderboard_type_number leaderboard_type_time_mins_secs cmpfunc_never cmpfunc_less cmpfunc_equal cmpfunc_lessequal cmpfunc_greater cmpfunc_notequal cmpfunc_greaterequal cmpfunc_always cull_noculling cull_clockwise cull_counterclockwise lighttype_dir lighttype_point iap_ev_storeload iap_ev_product iap_ev_purchase iap_ev_consume iap_ev_restore iap_storeload_ok iap_storeload_failed iap_status_uninitialised iap_status_unavailable iap_status_loading iap_status_available iap_status_processing iap_status_restoring iap_failed iap_unavailable iap_available iap_purchased iap_canceled iap_refunded fb_login_default fb_login_fallback_to_webview fb_login_no_fallback_to_webview fb_login_forcing_webview fb_login_use_system_account fb_login_forcing_safari  phy_joint_anchor_1_x phy_joint_anchor_1_y phy_joint_anchor_2_x phy_joint_anchor_2_y phy_joint_reaction_force_x phy_joint_reaction_force_y phy_joint_reaction_torque phy_joint_motor_speed phy_joint_angle phy_joint_motor_torque phy_joint_max_motor_torque phy_joint_translation phy_joint_speed phy_joint_motor_force phy_joint_max_motor_force phy_joint_length_1 phy_joint_length_2 phy_joint_damping_ratio phy_joint_frequency phy_joint_lower_angle_limit phy_joint_upper_angle_limit phy_joint_angle_limits phy_joint_max_length phy_joint_max_torque phy_joint_max_force phy_debug_render_aabb phy_debug_render_collision_pairs phy_debug_render_coms phy_debug_render_core_shapes phy_debug_render_joints phy_debug_render_obb phy_debug_render_shapes  phy_particle_flag_water phy_particle_flag_zombie phy_particle_flag_wall phy_particle_flag_spring phy_particle_flag_elastic phy_particle_flag_viscous phy_particle_flag_powder phy_particle_flag_tensile phy_particle_flag_colourmixing phy_particle_flag_colormixing phy_particle_group_flag_solid phy_particle_group_flag_rigid phy_particle_data_flag_typeflags phy_particle_data_flag_position phy_particle_data_flag_velocity phy_particle_data_flag_colour phy_particle_data_flag_color phy_particle_data_flag_category  achievement_our_info achievement_friends_info achievement_leaderboard_info achievement_achievement_info achievement_filter_all_players achievement_filter_friends_only achievement_filter_favorites_only achievement_type_achievement_challenge achievement_type_score_challenge achievement_pic_loaded  achievement_show_ui achievement_show_profile achievement_show_leaderboard achievement_show_achievement achievement_show_bank achievement_show_friend_picker achievement_show_purchase_prompt network_socket_tcp network_socket_udp network_socket_bluetooth network_type_connect network_type_disconnect network_type_data network_type_non_blocking_connect network_config_connect_timeout network_config_use_non_blocking_socket network_config_enable_reliable_udp network_config_disable_reliable_udp buffer_fixed buffer_grow buffer_wrap buffer_fast buffer_vbuffer buffer_network buffer_u8 buffer_s8 buffer_u16 buffer_s16 buffer_u32 buffer_s32 buffer_u64 buffer_f16 buffer_f32 buffer_f64 buffer_bool buffer_text buffer_string buffer_surface_copy buffer_seek_start buffer_seek_relative buffer_seek_end buffer_generalerror buffer_outofspace buffer_outofbounds buffer_invalidtype  text_type button_type input_type ANSI_CHARSET DEFAULT_CHARSET EASTEUROPE_CHARSET RUSSIAN_CHARSET SYMBOL_CHARSET SHIFTJIS_CHARSET HANGEUL_CHARSET GB2312_CHARSET CHINESEBIG5_CHARSET JOHAB_CHARSET HEBREW_CHARSET ARABIC_CHARSET GREEK_CHARSET TURKISH_CHARSET VIETNAMESE_CHARSET THAI_CHARSET MAC_CHARSET BALTIC_CHARSET OEM_CHARSET  gp_face1 gp_face2 gp_face3 gp_face4 gp_shoulderl gp_shoulderr gp_shoulderlb gp_shoulderrb gp_select gp_start gp_stickl gp_stickr gp_padu gp_padd gp_padl gp_padr gp_axislh gp_axislv gp_axisrh gp_axisrv ov_friends ov_community ov_players ov_settings ov_gamegroup ov_achievements lb_sort_none lb_sort_ascending lb_sort_descending lb_disp_none lb_disp_numeric lb_disp_time_sec lb_disp_time_ms ugc_result_success ugc_filetype_community ugc_filetype_microtrans ugc_visibility_public ugc_visibility_friends_only ugc_visibility_private ugc_query_RankedByVote ugc_query_RankedByPublicationDate ugc_query_AcceptedForGameRankedByAcceptanceDate ugc_query_RankedByTrend ugc_query_FavoritedByFriendsRankedByPublicationDate ugc_query_CreatedByFriendsRankedByPublicationDate ugc_query_RankedByNumTimesReported ugc_query_CreatedByFollowedUsersRankedByPublicationDate ugc_query_NotYetRated ugc_query_RankedByTotalVotesAsc ugc_query_RankedByVotesUp ugc_query_RankedByTextSearch ugc_sortorder_CreationOrderDesc ugc_sortorder_CreationOrderAsc ugc_sortorder_TitleAsc ugc_sortorder_LastUpdatedDesc ugc_sortorder_SubscriptionDateDesc ugc_sortorder_VoteScoreDesc ugc_sortorder_ForModeration ugc_list_Published ugc_list_VotedOn ugc_list_VotedUp ugc_list_VotedDown ugc_list_WillVoteLater ugc_list_Favorited ugc_list_Subscribed ugc_list_UsedOrPlayed ugc_list_Followed ugc_match_Items ugc_match_Items_Mtx ugc_match_Items_ReadyToUse ugc_match_Collections ugc_match_Artwork ugc_match_Videos ugc_match_Screenshots ugc_match_AllGuides ugc_match_WebGuides ugc_match_IntegratedGuides ugc_match_UsableInGame ugc_match_ControllerBindings  vertex_usage_position vertex_usage_colour vertex_usage_color vertex_usage_normal vertex_usage_texcoord vertex_usage_textcoord vertex_usage_blendweight vertex_usage_blendindices vertex_usage_psize vertex_usage_tangent vertex_usage_binormal vertex_usage_fog vertex_usage_depth vertex_usage_sample vertex_type_float1 vertex_type_float2 vertex_type_float3 vertex_type_float4 vertex_type_colour vertex_type_color vertex_type_ubyte4 layerelementtype_undefined layerelementtype_background layerelementtype_instance layerelementtype_oldtilemap layerelementtype_sprite layerelementtype_tilemap layerelementtype_particlesystem layerelementtype_tile tile_rotate tile_flip tile_mirror tile_index_mask kbv_type_default kbv_type_ascii kbv_type_url kbv_type_email kbv_type_numbers kbv_type_phone kbv_type_phone_name kbv_returnkey_default kbv_returnkey_go kbv_returnkey_google kbv_returnkey_join kbv_returnkey_next kbv_returnkey_route kbv_returnkey_search kbv_returnkey_send kbv_returnkey_yahoo kbv_returnkey_done kbv_returnkey_continue kbv_returnkey_emergency kbv_autocapitalize_none kbv_autocapitalize_words kbv_autocapitalize_sentences kbv_autocapitalize_characters",
 symbol:"argument_relative argument argument0 argument1 argument2 argument3 argument4 argument5 argument6 argument7 argument8 argument9 argument10 argument11 argument12 argument13 argument14 argument15 argument_count x y xprevious yprevious xstart ystart hspeed vspeed direction speed friction gravity gravity_direction path_index path_position path_positionprevious path_speed path_scale path_orientation path_endaction object_index id solid persistent mask_index instance_count instance_id room_speed fps fps_real current_time current_year current_month current_day current_weekday current_hour current_minute current_second alarm timeline_index timeline_position timeline_speed timeline_running timeline_loop room room_first room_last room_width room_height room_caption room_persistent score lives health show_score show_lives show_health caption_score caption_lives caption_health event_type event_number event_object event_action application_surface gamemaker_pro gamemaker_registered gamemaker_version error_occurred error_last debug_mode keyboard_key keyboard_lastkey keyboard_lastchar keyboard_string mouse_x mouse_y mouse_button mouse_lastbutton cursor_sprite visible sprite_index sprite_width sprite_height sprite_xoffset sprite_yoffset image_number image_index image_speed depth image_xscale image_yscale image_angle image_alpha image_blend bbox_left bbox_right bbox_top bbox_bottom layer background_colour  background_showcolour background_color background_showcolor view_enabled view_current view_visible view_xview view_yview view_wview view_hview view_xport view_yport view_wport view_hport view_angle view_hborder view_vborder view_hspeed view_vspeed view_object view_surface_id view_camera game_id game_display_name game_project_name game_save_id working_directory temp_directory program_directory browser_width browser_height os_type os_device os_browser os_version display_aa async_load delta_time webgl_enabled event_data iap_data phy_rotation phy_position_x phy_position_y phy_angular_velocity phy_linear_velocity_x phy_linear_velocity_y phy_speed_x phy_speed_y phy_speed phy_angular_damping phy_linear_damping phy_bullet phy_fixed_rotation phy_active phy_mass phy_inertia phy_com_x phy_com_y phy_dynamic phy_kinematic phy_sleeping phy_collision_points phy_collision_x phy_collision_y phy_col_normal_x phy_col_normal_y phy_position_xprevious phy_position_yprevious"},
 contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE]}});b.registerLanguage("go",function(a){var b={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};
-return{aliases:["golang"],keywords:b,illegal:"</",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",variants:[a.QUOTE_STRING_MODE,{begin:"'",end:"[^\\\\]'"},{begin:"`",end:"`"}]},{className:"number",variants:[{begin:a.C_NUMBER_RE+"[i]",relevance:1},a.C_NUMBER_MODE]},{begin:/:=/},{className:"function",beginKeywords:"func",end:"\\s*(\\{|$)",excludeEnd:!0,contains:[a.TITLE_MODE,{className:"params",begin:/\(/,end:/\)/,keywords:b,illegal:/["']/}]}]}});b.registerLanguage("golo",
-function(a){return{keywords:{keyword:"println readln print import module function local return let var while for foreach times in case when match with break continue augment augmentation each find filter reduce if then else otherwise try catch finally raise throw orIfNull DynamicObject|10 DynamicVariable struct Observable map set vector list array",literal:"true false null"},contains:[a.HASH_COMMENT_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("gradle",
-function(a){return{case_insensitive:!0,keywords:{keyword:"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine"},
+return{aliases:["golang"],keywords:b,illegal:"</",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",variants:[a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,{begin:"`",end:"`"}]},{className:"number",variants:[{begin:a.C_NUMBER_RE+"[i]",relevance:1},a.C_NUMBER_MODE]},{begin:/:=/},{className:"function",beginKeywords:"func",end:"\\s*(\\{|$)",excludeEnd:!0,contains:[a.TITLE_MODE,{className:"params",begin:/\(/,end:/\)/,keywords:b,illegal:/["']/}]}]}});b.registerLanguage("golo",function(a){return{keywords:{keyword:"println readln print import module function local return let var while for foreach times in case when match with break continue augment augmentation each find filter reduce if then else otherwise try catch finally raise throw orIfNull DynamicObject|10 DynamicVariable struct Observable map set vector list array",
+literal:"true false null"},contains:[a.HASH_COMMENT_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("gradle",function(a){return{case_insensitive:!0,keywords:{keyword:"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine"},
 contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.NUMBER_MODE,a.REGEXP_MODE]}});b.registerLanguage("groovy",function(a){return{keywords:{literal:"true false null",keyword:"byte short char int long boolean float double void def as in assert trait super this abstract static volatile transient public private protected synchronized final class interface enum if else for while switch case break default continue throw throws try catch finally implements extends new import package return instanceof"},
 contains:[a.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",begin:'"""',end:'"""'},{className:"string",begin:"'''",end:"'''"},{className:"string",begin:"\\$/",end:"/\\$",relevance:10},a.APOS_STRING_MODE,{className:"regexp",begin:/~?\/[^\/\n]+\//,contains:[a.BACKSLASH_ESCAPE]},a.QUOTE_STRING_MODE,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},a.BINARY_NUMBER_MODE,
 {className:"class",beginKeywords:"class interface trait enum",end:"{",illegal:":",contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"},{className:"string",begin:/[^\?]{0}[A-Za-z0-9_$]+ *:/},{begin:/\?/,end:/:/},{className:"symbol",begin:"^\\s*[A-Za-z0-9_$]+:",relevance:0}],illegal:/#|<\//}});b.registerLanguage("haml",function(a){return{case_insensitive:!0,contains:[{className:"meta",begin:"^!!!( (5|1\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\b.*))?$",
@@ -288,7 +289,7 @@
 c=[a.COMMENT("--(?!\\[=*\\[)","$"),a.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[b],relevance:10})];return{lexemes:a.UNDERSCORE_IDENT_RE,keywords:{literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstringmodule next pairs pcall print rawequal rawget rawset require select setfenvsetmetatable tonumber tostring type unpack xpcall arg selfcoroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},
 contains:c.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[a.inherit(a.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:c}].concat(c)},a.C_NUMBER_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[b],relevance:5}])}});b.registerLanguage("makefile",function(a){var b={className:"variable",variants:[{begin:"\\$\\("+a.UNDERSCORE_IDENT_RE+"\\)",
 contains:[a.BACKSLASH_ESCAPE]},{begin:/\$[@%<?\^\+\*]/}]};return{aliases:["mk","mak"],keywords:"define endef undefine ifdef ifndef ifeq ifneq else endif include -include sinclude override export unexport private vpath",lexemes:/[\w-]+/,contains:[a.HASH_COMMENT_MODE,b,{className:"string",begin:/"/,end:/"/,contains:[a.BACKSLASH_ESCAPE,b]},{className:"variable",begin:/\$\([\w-]+\s/,end:/\)/,keywords:{built_in:"subst patsubst strip findstring filter filter-out sort word wordlist firstword lastword dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath error warning shell origin flavor foreach if or and call eval file value"},
-contains:[b]},{begin:"^"+a.UNDERSCORE_IDENT_RE+"\\s*[:+?]?=",illegal:"\\n",returnBegin:!0,contains:[{begin:"^"+a.UNDERSCORE_IDENT_RE,end:"[:+?]?=",excludeEnd:!0}]},{className:"meta",begin:/^\.PHONY:/,end:/$/,keywords:{"meta-keyword":".PHONY"},lexemes:/[\.\w]+/},{className:"section",begin:/^[^\s]+:/,end:/$/,contains:[b]}]}});b.registerLanguage("mathematica",function(a){return{aliases:["mma","wl"],lexemes:"(\\$|\\b)"+a.IDENT_RE+"\\b",keywords:"AASTriangle AbelianGroup Abort AbortKernels AbortProtect AbortScheduledTask Above Abs AbsArg AbsArgPlot Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AcceptanceThreshold AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Activate Active ActiveClassification ActiveClassificationObject ActiveItem ActivePrediction ActivePredictionObject ActiveStyle AcyclicGraphQ AddOnHelpPath AddSides AddTo AddToSearchIndex AddUsers AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AdministrativeDivisionData AffineHalfSpace AffineSpace AffineStateSpaceModel AffineTransform After AggregatedEntityClass AggregationLayer AircraftData AirportData AirPressureData AirTemperatureData AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowAdultContent AllowedCloudExtraParameters AllowedCloudParameterExtensions AllowedDimensions AllowedFrequencyRange AllowedHeads AllowGroupClose AllowIncomplete AllowInlineCells AllowKernelInitialization AllowLooseGrammar AllowReverseGroupClose AllowScriptLevelChange AllTrue Alphabet AlphabeticOrder AlphabeticSort AlphaChannel AlternateImage AlternatingFactorial AlternatingGroup AlternativeHypothesis Alternatives AltitudeMethod AmbientLight AmbiguityFunction AmbiguityList Analytic AnatomyData AnatomyForm AnatomyPlot3D AnatomySkinStyle AnatomyStyling AnchoredSearch And AndersonDarlingTest AngerJ AngleBisector AngleBracket AnglePath AnglePath3D AngleVector AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning AnimationRunTime AnimationTimeIndex Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotate Annotation AnnotationDelete AnnotationNames AnnotationRules AnnotationValue Annuity AnnuityDue Annulus AnomalyDetection AnomalyDetectorFunction Anonymous Antialiasing AntihermitianMatrixQ Antisymmetric AntisymmetricMatrixQ Antonyms AnyOrder AnySubset AnyTrue Apart ApartSquareFree APIFunction Appearance AppearanceElements AppearanceRules AppellF1 Append AppendCheck AppendLayer AppendTo ApplicationIdentificationKey Apply ApplySides ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcCurvature ARCHProcess ArcLength ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Area Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess Around AroundReplace ARProcess Array ArrayComponents ArrayDepth ArrayFilter ArrayFlatten ArrayMesh ArrayPad ArrayPlot ArrayQ ArrayResample ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads ASATriangle Ask AskAppend AskConfirm AskDisplay AskedQ AskedValue AskFunction AskState AskTemplateDisplay AspectRatio AspectRatioFixed Assert AssociateTo Association AssociationFormat AssociationMap AssociationQ AssociationThread AssumeDeterministic Assuming Assumptions AstronomicalData AsymptoticDSolveValue AsymptoticEqual AsymptoticEquivalent AsymptoticGreater AsymptoticGreaterEqual AsymptoticIntegrate AsymptoticLess AsymptoticLessEqual AsymptoticOutputTracker AsymptoticRSolveValue AsymptoticSolve AsymptoticSum Asynchronous AsynchronousTaskObject AsynchronousTasks Atom AtomCoordinates AtomCount AtomDiagramCoordinates AtomList AtomQ AttentionLayer Attributes Audio AudioAmplify AudioAnnotate AudioAnnotationLookup AudioBlockMap AudioCapture AudioChannelAssignment AudioChannelCombine AudioChannelMix AudioChannels AudioChannelSeparate AudioData AudioDelay AudioDelete AudioDevice AudioDistance AudioFade AudioFrequencyShift AudioGenerator AudioIdentify AudioInputDevice AudioInsert AudioIntervals AudioJoin AudioLabel AudioLength AudioLocalMeasurements AudioLooping AudioLoudness AudioMeasurements AudioNormalize AudioOutputDevice AudioOverlay AudioPad AudioPan AudioPartition AudioPause AudioPitchShift AudioPlay AudioPlot AudioQ AudioRecord AudioReplace AudioResample AudioReverb AudioSampleRate AudioSpectralMap AudioSpectralTransformation AudioSplit AudioStop AudioStream AudioStreams AudioTimeStretch AudioTrim AudioType AugmentedPolyhedron AugmentedSymmetricPolynomial Authenticate Authentication AuthenticationDialog AutoAction Autocomplete AutocompletionFunction AutoCopy AutocorrelationTest AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutoQuoteCharacters AutoRefreshed AutoRemove AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords AutoSubmitting Axes AxesEdge AxesLabel AxesOrigin AxesStyle AxiomaticTheory AxisBabyMonsterGroupB Back Background BackgroundAppearance BackgroundTasksSettings Backslash Backsubstitution Backward Ball Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarcodeImage BarcodeRecognize BaringhausHenzeTest BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseDecode BaseEncode BaseForm Baseline BaselinePosition BaseStyle BasicRecurrentLayer BatchNormalizationLayer BatchSize BatesDistribution BattleLemarieWavelet BayesianMaximization BayesianMaximizationObject BayesianMinimization BayesianMinimizationObject Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized Between BetweennessCentrality BeveledPolyhedron BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryDeserialize BinaryDistance BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinarySerialize BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BiquadraticFilterModel BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor BiweightLocation BiweightMidvariance Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockchainAddressData BlockchainBase BlockchainBlockData BlockchainContractValue BlockchainData BlockchainGet BlockchainKeyEncode BlockchainPut BlockchainTokenData BlockchainTransaction BlockchainTransactionData BlockchainTransactionSign BlockchainTransactionSubmit BlockMap BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bond BondCount BondList BondQ Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms BooleanQ BooleanRegion Booleans BooleanStrings BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryDiscretizeGraphics BoundaryDiscretizeRegion BoundaryMesh BoundaryMeshRegion BoundaryMeshRegionQ BoundaryStyle BoundedRegionQ BoundingRegion Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxObject BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break BridgeData BrightnessEqualize BroadcastStationData Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurve3DBoxOptions BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BSplineSurface3DBoxOptions BubbleChart BubbleChart3D BubbleScale BubbleSizes BuildingData BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteArray ByteArrayFormat ByteArrayQ ByteArrayToString ByteCount ByteOrderingC CachedValue CacheGraphics CachePersistence CalendarConvert CalendarData CalendarType Callout CalloutMarker CalloutStyle CallPacket CanberraDistance Cancel CancelButton CandlestickChart CanonicalGraph CanonicalizePolygon CanonicalizePolyhedron CanonicalName CanonicalWarpingCorrespondence CanonicalWarpingDistance CantorMesh CantorStaircase Cap CapForm CapitalDifferentialD Capitalize CapsuleShape CaptureRunning CardinalBSplineBasis CarlemanLinearize CarmichaelLambda CaseOrdering Cases CaseSensitive Cashflow Casoratian Catalan CatalanNumber Catch Catenate CatenateLayer CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling CelestialSystem Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEvaluationLanguage CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellLabelStyle CellLabelTemplate CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterArray CenterDot CentralFeature CentralMoment CentralMomentGeneratingFunction Cepstrogram CepstrogramArray CepstrumArray CForm ChampernowneNumber ChangeOptions ChannelBase ChannelBrokerAction ChannelDatabin ChannelHistoryLength ChannelListen ChannelListener ChannelListeners ChannelListenerWait ChannelObject ChannelPreSendFunction ChannelReceiverFunction ChannelSend ChannelSubscribers ChanVeseBinarize Character CharacterCounts CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterName CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop ChromaticityPlot ChromaticityPlot3D ChromaticPolynomial Circle CircleBox CircleDot CircleMinus CirclePlus CirclePoints CircleThrough CircleTimes CirculantGraph CircularOrthogonalMatrixDistribution CircularQuaternionMatrixDistribution CircularRealMatrixDistribution CircularSymplecticMatrixDistribution CircularUnitaryMatrixDistribution Circumsphere CityData ClassifierFunction ClassifierInformation ClassifierMeasurements ClassifierMeasurementsObject Classify ClassPriors Clear ClearAll ClearAttributes ClearCookies ClearPermissions ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipPlanesStyle ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent CloudAccountData CloudBase CloudConnect CloudDeploy CloudDirectory CloudDisconnect CloudEvaluate CloudExport CloudExpression CloudExpressions CloudFunction CloudGet CloudImport CloudLoggingData CloudObject CloudObjectInformation CloudObjectInformationData CloudObjectNameFormat CloudObjects CloudObjectURLType CloudPublish CloudPut CloudRenderingMethod CloudSave CloudShare CloudSubmit CloudSymbol CloudUnshare ClusterClassify ClusterDissimilarityFunction ClusteringComponents ClusteringTree CMYKColor Coarse CodeAssistOptions Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorBalance ColorCombine ColorConvert ColorCoverage ColorData ColorDataFunction ColorDetect ColorDistance ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQ ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorsNear ColorSpace ColorToneMapping Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CombinedEntityClass CombinerFunction CometData CommonDefaultFormatTypes Commonest CommonestFilter CommonName CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompanyData CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledCodeFunction CompiledFunction CompilerOptions Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComplexListPlot ComplexPlot ComplexPlot3D ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries CompositeQ Composition CompoundElement CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData ComputeUncertainty Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath ConformAudio ConformImages Congruent ConicHullRegion ConicHullRegion3DBox ConicHullRegionBox ConicOptimization Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphComponents ConnectedGraphQ ConnectedMeshComponents ConnectedMoleculeComponents ConnectedMoleculeQ ConnectionSettings ConnectLibraryCallbackFunction ConnectSystemModelComponents ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray ConstantArrayLayer ConstantImage ConstantPlusLayer ConstantRegionQ Constants ConstantTimesLayer ConstellationData ConstrainedMax ConstrainedMin Construct Containing ContainsAll ContainsAny ContainsExactly ContainsNone ContainsOnly ContentFieldOptions ContentLocationFunction ContentObject ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTask ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean ContrastiveLossLayer Control ControlActive ControlAlignment ControlGroupContentsBox ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket ConvexHullMesh ConvexPolygonQ ConvexPolyhedronQ ConvolutionLayer Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CookieFunction Cookies CoordinateBoundingBox CoordinateBoundingBoxArray CoordinateBounds CoordinateBoundsArray CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDatabin CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CountDistinct CountDistinctBy CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Counts CountsBy Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateCellID CreateChannel CreateCloudExpression CreateDatabin CreateDataSystemModel CreateDialog CreateDirectory CreateDocument CreateFile CreateIntermediateDirectories CreateManagedLibraryExpression CreateNotebook CreatePalette CreatePalettePacket CreatePermissionsGroup CreateScheduledTask CreateSearchIndex CreateSystemModel CreateTemporary CreateUUID CreateWindow CriterionFunction CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossEntropyLossLayer CrossingCount CrossingDetect CrossingPolygon CrossMatrix Csc Csch CTCLossLayer Cube CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrencyConvert CurrentDate CurrentImage CurrentlySpeakingPacket CurrentNotebookImage CurrentScreenImage CurrentValue Curry CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecompositionD DagumDistribution DamData DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DatabaseConnect DatabaseDisconnect DatabaseReference Databin DatabinAdd DatabinRemove Databins DatabinUpload DataCompression DataDistribution DataRange DataReversed Dataset Date DateBounds Dated DateDelimiters DateDifference DatedUnit DateFormat DateFunction DateHistogram DateList DateListLogPlot DateListPlot DateListStepPlot DateObject DateObjectQ DateOverlapsQ DatePattern DatePlus DateRange DateReduction DateString DateTicksFormat DateValue DateWithinQ DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayHemisphere DaylightQ DayMatchQ DayName DayNightTerminator DayPlus DayRange DayRound DeBruijnGraph DeBruijnSequence Debug DebugTag Decapitalize Decimal DecimalForm DeclareKnownSymbols DeclarePackage Decompose DeconvolutionLayer Decrement Decrypt DecryptFile DedekindEta DeepSpaceProbeData Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultPrintPrecision DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValue DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod DefineResourceFunction Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic DEigensystem DEigenvalues Deinitialization Del DelaunayMesh Delayed Deletable Delete DeleteAnomalies DeleteBorderComponents DeleteCases DeleteChannel DeleteCloudExpression DeleteContents DeleteDirectory DeleteDuplicates DeleteDuplicatesBy DeleteFile DeleteMissing DeleteObject DeletePermissionsKey DeleteSearchIndex DeleteSmallComponents DeleteStopwords DeleteWithContents DeletionWarning DelimitedArray DelimitedSequence Delimiter DelimiterFlashTime DelimiterMatching Delimiters DeliveryFunction Dendrogram Denominator DensityGraphics DensityHistogram DensityPlot DensityPlot3D DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DerivedKey DescriptorStateSpace DesignMatrix DestroyAfterEvaluation Det DeviceClose DeviceConfigure DeviceExecute DeviceExecuteAsynchronous DeviceObject DeviceOpen DeviceOpenQ DeviceRead DeviceReadBuffer DeviceReadLatest DeviceReadList DeviceReadTimeSeries Devices DeviceStreams DeviceWrite DeviceWriteBuffer DGaussianWavelet DiacriticalPositioning Diagonal DiagonalizableMatrixQ DiagonalMatrix DiagonalMatrixQ Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DictionaryWordQ DifferenceDelta DifferenceOrder DifferenceQuotient DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitalSignature DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralAngle DihedralGroup Dilation DimensionalCombinations DimensionalMeshComponents DimensionReduce DimensionReducerFunction DimensionReduction Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletBeta DirichletCharacter DirichletCondition DirichletConvolve DirichletDistribution DirichletEta DirichletL DirichletLambda DirichletTransform DirichletWindow DisableConsolePrintPacket DisableFormatting DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLimit DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscreteMaxLimit DiscreteMinLimit DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform DiscretizeGraphics DiscretizeRegion Discriminant DisjointQ Disjunction Disk DiskBox DiskMatrix DiskSegment Dispatch DispatchQ DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceMatrix DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers DivideSides Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentGenerator DocumentGeneratorInformation DocumentGeneratorInformationData DocumentGenerators DocumentNotebook DocumentWeightingRules Dodecahedron DomainRegistrationInformation DominantColors DOSTextFormat Dot DotDashed DotEqual DotLayer DotPlusLayer Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DropoutLayer DSolve DSolveValue Dt DualLinearProgramming DualPolyhedron DualSystemsModel DumpGet DumpSave DuplicateFreeQ Duration Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicGeoGraphics DynamicImage DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptionsE EarthImpactData EarthquakeData EccentricityCentrality Echo EchoFunction EclipseType EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeContract EdgeCost EdgeCount EdgeCoverQ EdgeCycleMatrix EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight EdgeWeightedGraphQ Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData ElementwiseLayer ElidedForms Eliminate EliminationOrder Ellipsoid EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmbedCode EmbeddedHTML EmbeddedService EmbeddingLayer EmbeddingObject EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EmptyRegion EnableConsolePrintPacket Enabled Encode Encrypt EncryptedObject EncryptFile End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfBuffer EndOfFile EndOfLine EndOfString EndPackage EngineEnvironment EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entity EntityClass EntityClassList EntityCopies EntityFunction EntityGroup EntityInstance EntityList EntityPrefetch EntityProperties EntityProperty EntityPropertyClass EntityRegister EntityStore EntityStores EntityTypeName EntityUnregister EntityValue Entropy EntropyFilter Environment Epilog EpilogFunction Equal EqualColumns EqualRows EqualTilde EqualTo EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EscapeRadius EstimatedBackground EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerAngles EulerCharacteristic EulerE EulerGamma EulerianGraphQ EulerMatrix EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluateScheduledTask EvaluationBox EvaluationCell EvaluationCompletionAction EvaluationData EvaluationElements EvaluationEnvironment EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels EventSeries ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludedLines ExcludedPhysicalQuantities ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog ExoplanetData Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi ExpirationDate Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportByteArray ExportForm ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpressionUUID ExpToTrig ExtendedEntityClass ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalBundle ExternalCall ExternalDataCharacterEncoding ExternalEvaluate ExternalFunction ExternalFunctionName ExternalObject ExternalOptions ExternalSessionObject ExternalSessions ExternalTypeSignature ExternalValue Extract ExtractArchive ExtractLayer ExtremeValueDistributionFaceForm FaceGrids FaceGridsStyle FacialFeatures Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail Failure FailureAction FailureDistribution FailureQ False FareySequence FARIMAProcess FeatureDistance FeatureExtract FeatureExtraction FeatureExtractor FeatureExtractorFunction FeatureNames FeatureNearest FeatureSpacePlot FeatureSpacePlot3D FeatureTypes FEDisableConsolePrintPacket FeedbackLinearize FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket FetalGrowthData Fibonacci Fibonorial FieldCompletionFunction FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileConvert FileDate FileExistsQ FileExtension FileFormat FileHandler FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameForms FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileSize FileSystemMap FileSystemScan FileTemplate FileTemplateApply FileType FilledCurve FilledCurveBox FilledCurveBoxOptions Filling FillingStyle FillingTransform FilteredEntityClass FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindAnomalies FindArgMax FindArgMin FindChannels FindClique FindClusters FindCookies FindCurvePath FindCycle FindDevices FindDistribution FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEdgeIndependentPaths FindEquationalProof FindEulerianCycle FindExternalEvaluators FindFaces FindFile FindFit FindFormula FindFundamentalCycles FindGeneratingFunction FindGeoLocation FindGeometricConjectures FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindHamiltonianPath FindHiddenMarkovStates FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMatchingColor FindMaximum FindMaximumFlow FindMaxValue FindMeshDefects FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindMoleculeSubstructure FindPath FindPeaks FindPermutation FindPostmanTour FindProcessParameters FindRepeat FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindSpanningTree FindSystemModelEquilibrium FindTextualAnswer FindThreshold FindTransientRepeat FindVertexCover FindVertexCut FindVertexIndependentPaths Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstCase FirstPassageTimeDistribution FirstPosition FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FitRegularization FittedModel FixedOrder FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlattenLayer FlatTopWindow FlipView Floor FlowPolynomial FlushPrintOutputPacket Fold FoldList FoldPair FoldPairList FollowRedirects Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FormControl FormFunction FormLayoutFunction FormObject FormPage FormTheme FormulaData FormulaLookup FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalGaussianNoiseProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameRate FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrenetSerretSystem FrequencySamplingFilterKernel FresnelC FresnelF FresnelG FresnelS Friday FrobeniusNumber FrobeniusSolve FromAbsoluteTime FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS FromEntity FromJulianDate FromLetterNumber FromPolarCoordinates FromRomanNumeral FromSphericalCoordinates FromUnixTime Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullInformationOutputRegulator FullOptions FullRegion FullSimplify Function FunctionCompile FunctionCompileExport FunctionCompileExportByteArray FunctionCompileExportLibrary FunctionCompileExportString FunctionDomain FunctionExpand FunctionInterpolation FunctionPeriod FunctionRange FunctionSpace FussellVeselyImportanceGaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins GalaxyData GalleryView Gamma GammaDistribution GammaRegularized GapPenalty GARCHProcess GatedRecurrentLayer Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianOrthogonalMatrixDistribution GaussianSymplecticMatrixDistribution GaussianUnitaryMatrixDistribution GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateAsymmetricKeyPair GenerateConditions GeneratedCell GeneratedDocumentBinding GenerateDerivedKey GenerateDigitalSignature GenerateDocument GeneratedParameters GeneratedQuantityMagnitudes GenerateHTTPResponse GenerateSecuredAuthenticationKey GenerateSymmetricKey GeneratingFunction GeneratorDescription GeneratorHistoryLength GeneratorOutputType Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeoAntipode GeoArea GeoArraySize GeoBackground GeoBoundingBox GeoBounds GeoBoundsRegion GeoBubbleChart GeoCenter GeoCircle GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDisk GeoDisplacement GeoDistance GeoDistanceList GeoElevationData GeoEntities GeoGraphics GeogravityModelData GeoGridDirectionDifference GeoGridLines GeoGridLinesStyle GeoGridPosition GeoGridRange GeoGridRangePadding GeoGridUnitArea GeoGridUnitDistance GeoGridVector GeoGroup GeoHemisphere GeoHemisphereBoundary GeoHistogram GeoIdentify GeoImage GeoLabels GeoLength GeoListPlot GeoLocation GeologicalPeriodData GeomagneticModelData GeoMarker GeometricAssertion GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricScene GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoModel GeoNearest GeoPath GeoPosition GeoPositionENU GeoPositionXYZ GeoProjection GeoProjectionData GeoRange GeoRangePadding GeoRegionValuePlot GeoResolution GeoScaleBar GeoServer GeoSmoothHistogram GeoStreamPlot GeoStyling GeoStylingImageFunction GeoVariant GeoVector GeoVectorENU GeoVectorPlot GeoVectorXYZ GeoVisibleRegion GeoVisibleRegionBoundary GeoWithinQ GeoZoomLevel GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenAngle GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter GrammarApply GrammarRules GrammarToken Graph Graph3D GraphAssortativity GraphAutomorphismGroup GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel Greater GreaterEqual GreaterEqualLess GreaterEqualThan GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterThan GreaterTilde Green GreenFunction Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupBy GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators Groupings GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain GroupTogetherGrouping GroupTogetherNestedGrouping GrowCutComponents Gudermannian GuidedFilter GumbelDistributionHaarWavelet HadamardMatrix HalfLine HalfNormalDistribution HalfPlane HalfSpace HamiltonianGraphQ HammingDistance HammingWindow HandlerFunctions HandlerFunctionsKeys HankelH1 HankelH2 HankelMatrix HankelTransform HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash Haversine HazardFunction Head HeadCompose HeaderLines Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings Here HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenMarkovProcess HiddenSurface Highlighted HighlightGraph HighlightImage HighlightMesh HighpassFilter HigmanSimsGroupHS HilbertCurve HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HistoricalPeriodData HitMissTransform HITSCentrality HjorthDistribution HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HostLookup HotellingTSquareDistribution HoytDistribution HTMLSave HTTPErrorResponse HTTPRedirect HTTPRequest HTTPRequestData HTTPResponse Hue HumanGrowthData HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyperplane Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestDataI IconData Iconize IconizedObject IconRules Icosahedron Identity IdentityMatrix If IgnoreCase IgnoreDiacritics IgnorePunctuation IgnoreSpellCheck IgnoringInactive Im Image Image3D Image3DProjection Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageApplyIndexed ImageAspectRatio ImageAssemble ImageAugmentationLayer ImageBoundingBoxes ImageCache ImageCacheValid ImageCapture ImageCaptureFunction ImageCases ImageChannels ImageClip ImageCollage ImageColorSpace ImageCompose ImageContainsQ ImageContents ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDisplacements ImageDistance ImageEffect ImageExposureCombine ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageFocusCombine ImageForestingComponents ImageFormattingWidth ImageForwardTransformation ImageGraphics ImageHistogram ImageIdentify ImageInstanceQ ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarker ImageMarkers ImageMeasurements ImageMesh ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImagePosition ImagePreviewFunction ImagePyramid ImagePyramidApply ImageQ ImageRangeCache ImageRecolor ImageReflect ImageRegion ImageResize ImageResolution ImageRestyle ImageRotate ImageRotated ImageSaliencyFilter ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions ImagingDevice ImplicitRegion Implies Import ImportAutoReplacements ImportByteArray ImportOptions ImportString ImprovementImportance In Inactivate Inactive IncidenceGraph IncidenceList IncidenceMatrix IncludeAromaticBonds IncludeConstantBasis IncludeDefinitions IncludeDirectories IncludeFileExtension IncludeGeneratorTasks IncludeHydrogens IncludeInflections IncludeMetaInformation IncludePods IncludeQuantities IncludeRelatedTables IncludeSingularTerm IncludeWindowTimes Increment IndefiniteMatrixQ Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentPhysicalQuantity IndependentUnit IndependentUnitDimension IndependentVertexSetQ Indeterminate IndeterminateThreshold IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers InfiniteLine InfinitePlane Infinity Infix InflationAdjust InflationMethod Information InformationData InformationDataGrid Inherited InheritScope InhomogeneousPoissonProcess InitialEvaluationHistory Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InitializationObjects InitializationValue Initialize InitialSeeding InlineCounterAssignments InlineCounterIncrements InlineRules Inner InnerPolygon InnerPolyhedron Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionFunction InsertionPointObject InsertLinebreaks InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Insphere Install InstallService InstanceNormalizationLayer InString Integer IntegerDigits IntegerExponent IntegerLength IntegerName IntegerPart IntegerPartitions IntegerQ IntegerReverse Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction Interpreter InterpretTemplate InterquartileRange Interrupt InterruptSettings IntersectingQ Intersection Interval IntervalIntersection IntervalMarkers IntervalMarkersStyle IntervalMemberQ IntervalSlider IntervalUnion Into Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHankelTransform InverseHaversine InverseImagePyramid InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InverseMellinTransform InversePermutation InverseRadon InverseRadonTransform InverseSeries InverseShortTimeFourier InverseSpectrogram InverseSurvivalFunction InverseTransformedRegion InverseWaveletTransform InverseWeierstrassP InverseWishartMatrixDistribution InverseZTransform Invisible InvisibleApplication InvisibleTimes IPAddress IrreduciblePolynomialQ IslandData IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemAspectRatio ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcessJaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join JoinAcross Joined JoinedCurve JoinedCurveBox JoinedCurveBoxOptions JoinForm JordanDecomposition JordanModelDecomposition JulianDate JuliaSetBoettcher JuliaSetIterationCount JuliaSetPlot JuliaSetPointsK KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KEdgeConnectedComponents KEdgeConnectedGraphQ KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelFunction KernelMixtureDistribution Kernels Ket Key KeyCollisionFunction KeyComplement KeyDrop KeyDropFrom KeyExistsQ KeyFreeQ KeyIntersection KeyMap KeyMemberQ KeypointStrength Keys KeySelect KeySort KeySortBy KeyTake KeyUnion KeyValueMap KeyValuePattern Khinchin KillProcess KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnapsackSolve KnightTourGraph KnotData KnownUnitQ KochCurve KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter KVertexConnectedComponents KVertexConnectedGraphQLABColor Label Labeled LabeledSlider LabelingFunction LabelingSize LabelStyle LabelVisibility LaguerreL LakeData LambdaComponents LambertW LaminaData LanczosWindow LandauDistribution Language LanguageCategory LanguageData LanguageIdentify LanguageOptions LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCHColor LCM LeaderSize LeafCount LeapYearQ LearnDistribution LearnedDistribution LearningRate LearningRateMultipliers LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessEqualThan LessFullEqual LessGreater LessLess LessSlantEqual LessThan LessTilde LetterCharacter LetterCounts LetterNumber LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryDataType LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox Line3DBoxOptions LinearFilter LinearFractionalOptimization LinearFractionalTransform LinearGradientImage LinearizingTransformationData LinearLayer LinearModelFit LinearOffsetFunction LinearOptimization LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBoxOptions LineBreak LinebreakAdjustments LineBreakChart LinebreakSemicolonWeighting LineBreakWithin LineColor LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRankCentrality LinkRead LinkReadHeld LinkReadyQ Links LinkService LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot ListDensityPlot3D Listen ListFormat ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListSliceContourPlot3D ListSliceDensityPlot3D ListSliceVectorPlot3D ListStepPlot ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalAdaptiveBinarize LocalCache LocalClusteringCoefficient LocalizeDefinitions LocalizeVariables LocalObject LocalObjects LocalResponseNormalizationLayer LocalSubmit LocalSymbol LocalTime LocalTimeZone LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogisticSigmoid LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongestOrderedSequence LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow LongShortTermMemoryLayer Lookup Loopback LoopFreeGraphQ LossFunction LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowerTriangularMatrixQ LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LunarEclipse LUVColor LyapunovSolve LyonsGroupLyMachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MailAddressValidation MailExecute MailFolder MailItem MailReceiverFunction MailResponseFunction MailSearch MailServerConnect MailServerConnection MailSettings MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules ManagedLibraryExpressionID ManagedLibraryExpressionQ MandelbrotSetBoettcher MandelbrotSetDistance MandelbrotSetIterationCount MandelbrotSetMemberQ MandelbrotSetPlot MangoldtLambda ManhattanDistance Manipulate Manipulator MannedSpaceMissionData MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarchenkoPasturDistribution MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicalFunctionData MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixNormalDistribution MatrixPlot MatrixPower MatrixPropertyDistribution MatrixQ MatrixRank MatrixTDistribution Max MaxBend MaxCellMeasure MaxColorDistance MaxDetect MaxDuration MaxExtraBandwidths MaxExtraConditions MaxFeatureDisplacement MaxFeatures MaxFilter MaximalBy Maximize MaxItems MaxIterations MaxLimit MaxMemoryUsed MaxMixtureKernels MaxOverlapFraction MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxTrainingRounds MaxValue MaxwellDistribution MaxWordGap McLaughlinGroupMcL Mean MeanAbsoluteLossLayer MeanAround MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter MeanSquaredLossLayer Median MedianDeviation MedianFilter MedicalTestData Medium MeijerG MeijerGReduce MeixnerDistribution MellinConvolve MellinTransform MemberQ MemoryAvailable MemoryConstrained MemoryConstraint MemoryInUse MengerMesh Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuList MenuPacket MenuSortingValue MenuStyle MenuView Merge MergeDifferences MergingFunction MersennePrimeExponent MersennePrimeExponentQ Mesh MeshCellCentroid MeshCellCount MeshCellHighlight MeshCellIndex MeshCellLabel MeshCellMarker MeshCellMeasure MeshCellQuality MeshCells MeshCellShapeFunction MeshCellStyle MeshCoordinates MeshFunctions MeshPrimitives MeshQualityGoal MeshRange MeshRefinementFunction MeshRegion MeshRegionQ MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageObject MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation MeteorShowerData Method MethodOptions MexicanHatWavelet MeyerWavelet Midpoint Min MinColorDistance MinDetect MineralData MinFilter MinimalBy MinimalPolynomial MinimalStateSpaceModel Minimize MinimumTimeIncrement MinIntervalSize MinkowskiQuestionMark MinLimit MinMax MinorPlanetData Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingBehavior MissingDataMethod MissingDataRules MissingQ MissingString MissingStyle MissingValuePattern MittagLefflerE MixedFractionParts MixedGraphQ MixedMagnitude MixedRadix MixedRadixQuantity MixedUnit MixtureDistribution Mod Modal Mode Modular ModularInverse ModularLambda Module Modulus MoebiusMu Molecule MoleculeContainsQ MoleculeEquivalentQ MoleculeGraph MoleculeModify MoleculePattern MoleculePlot MoleculePlot3D MoleculeProperty MoleculeQ MoleculeValue Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction MomentOfInertia Monday Monitor MonomialList MonomialOrder MonsterGroupM MoonPhase MoonPosition MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform MortalityData Most MountainData MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovieData MovingAverage MovingMap MovingMedian MoyalDistribution Multicolumn MultiedgeStyle MultigraphQ MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity MultiplySides Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistributionN NakagamiDistribution NameQ Names NamespaceBox NamespaceBoxOptions Nand NArgMax NArgMin NBernoulliB NBodySimulation NBodySimulationData NCache NDEigensystem NDEigenvalues NDSolve NDSolveValue Nearest NearestFunction NearestNeighborGraph NearestTo NebulaData NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeDefiniteMatrixQ NegativeIntegers NegativeMultinomialDistribution NegativeRationals NegativeReals NegativeSemidefiniteMatrixQ NeighborhoodData NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestGraph NestList NestWhile NestWhileList NetAppend NetBidirectionalOperator NetChain NetDecoder NetDelete NetDrop NetEncoder NetEvaluationMode NetExtract NetFlatten NetFoldOperator NetGraph NetInformation NetInitialize NetInsert NetInsertSharedArrays NetJoin NetMapOperator NetMapThreadOperator NetMeasurements NetModel NetNestOperator NetPairEmbeddingOperator NetPort NetPortGradient NetPrepend NetRename NetReplace NetReplacePart NetSharedArray NetStateObject NetTake NetTrain NetTrainResultsObject NetworkPacketCapture NetworkPacketRecording NetworkPacketRecordingDuring NetworkPacketTrace NeumannValue NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextCell NextDate NextPrime NextScheduledTaskTime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NightHemisphere NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants NondimensionalizationTransform None NoneTrue NonlinearModelFit NonlinearStateSpaceModel NonlocalMeansFilter NonNegative NonNegativeIntegers NonNegativeRationals NonNegativeReals NonPositive NonPositiveIntegers NonPositiveRationals NonPositiveReals Nor NorlundB Norm Normal NormalDistribution NormalGrouping NormalizationLayer Normalize Normalized NormalizedSquaredEuclideanDistance NormalMatrixQ NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookImport NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookTemplate NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde Nothing NotHumpDownHump NotHumpEqual NotificationFunction NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar Now NoWhitespace NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms NuclearExplosionData NuclearReactorData Null NullRecords NullSpace NullWords Number NumberCompose NumberDecompose NumberExpand NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberLinePlot NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumeratorDenominator NumericalOrder NumericalSort NumericArray NumericArrayQ NumericArrayType NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlotO ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OceanData Octahedron OddQ Off Offset OLEData On ONanGroupON Once OneIdentity Opacity OpacityFunction OpacityFunctionScaling Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionalElement OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering OrderingBy OrderingLayer Orderless OrderlessPatternSequence OrnsteinUhlenbeckProcess Orthogonalize OrthogonalMatrixQ Out Outer OuterPolygon OuterPolyhedron OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OverwriteTarget OwenT OwnValuesPackage PackingMethod PaddedForm Padding PaddingLayer PaddingSize PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageTheme PageWidth Pagination PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath PalindromeQ Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo Parallelepiped ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds Parallelogram ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParametricRegion ParentBox ParentCell ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParentNotebook ParetoDistribution ParetoPickandsDistribution ParkData Part PartBehavior PartialCorrelationFunction PartialD ParticleAcceleratorData ParticleData Partition PartitionGranularity PartitionsP PartitionsQ PartLayer PartOfSpeech PartProtection ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteAutoQuoteCharacters PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PeakDetect PeanoCurve PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PercentForm PerfectNumber PerfectNumberQ PerformanceGoal Perimeter PeriodicBoundaryCondition PeriodicInterpolation Periodogram PeriodogramArray Permanent Permissions PermissionsGroup PermissionsGroupMemberQ PermissionsGroups PermissionsKey PermissionsKeys PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PerpendicularBisector PersistenceLocation PersistenceTime PersistentObject PersistentObjects PersistentValue PersonData PERTDistribution PetersenGraph PhaseMargins PhaseRange PhysicalSystemData Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest PingTime Pink PitchRecognize Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarAngle PlanarGraph PlanarGraphQ PlanckRadiationLaw PlaneCurveData PlanetaryMoonData PlanetData PlantData Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLabels PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangeClipPlanesStyle PlotRangePadding PlotRegion PlotStyle PlotTheme Pluralize Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox Point3DBoxOptions PointBox PointBoxOptions PointFigureChart PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonalNumber PolygonAngle PolygonBox PolygonBoxOptions PolygonCoordinates PolygonDecomposition PolygonHoleScale PolygonIntersections PolygonScale Polyhedron PolyhedronAngle PolyhedronCoordinates PolyhedronData PolyhedronDecomposition PolyhedronGenus PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PoolingLayer PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position PositionIndex Positive PositiveDefiniteMatrixQ PositiveIntegers PositiveRationals PositiveReals PositiveSemidefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerRange PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement Predict PredictionRoot PredictorFunction PredictorInformation PredictorMeasurements PredictorMeasurementsObject PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependLayer PrependTo PreprocessingRules PreserveColor PreserveImageOptions Previous PreviousCell PreviousDate PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitivePolynomialQ PrimitiveRoot PrimitiveRootList PrincipalComponents PrincipalValue Print PrintableASCIIQ PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment Printout3D Printout3DPreviewer PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateKey PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessConnection ProcessDirectory ProcessEnvironment Processes ProcessEstimator ProcessInformation ProcessObject ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessStatus ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm ProofObject Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse PsychrometricPropertyData PublicKey PublisherID PulsarData PunctuationCharacter Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptionsQBinomial QFactorial QGamma QHypergeometricPFQ QnDispersion QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ QuadraticOptimization Quantile QuantilePlot Quantity QuantityArray QuantityDistribution QuantityForm QuantityMagnitude QuantityQ QuantityUnit QuantityVariable QuantityVariableCanonicalUnit QuantityVariableDimensions QuantityVariableIdentifier QuantityVariablePhysicalQuantity Quartics QuartileDeviation Quartiles QuartileSkewness Query QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainderRadialGradientImage RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RadonTransform RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Ramp Random RandomChoice RandomColor RandomComplex RandomEntity RandomFunction RandomGeoPosition RandomGraph RandomImage RandomInstance RandomInteger RandomPermutation RandomPoint RandomPolygon RandomPolyhedron RandomPrime RandomReal RandomSample RandomSeed RandomSeeding RandomVariate RandomWalkProcess RandomWord Range RangeFilter RangeSpecification RankedMax RankedMin RarerProbability Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadByteArray ReadLine ReadList ReadProtected ReadString Real RealAbs RealBlockDiagonalForm RealDigits RealExponent Reals RealSign Reap RecognitionPrior RecognitionThreshold Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RectangularRepeatingElement RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate Region RegionBinarize RegionBoundary RegionBounds RegionCentroid RegionDifference RegionDimension RegionDisjoint RegionDistance RegionDistanceFunction RegionEmbeddingDimension RegionEqual RegionFunction RegionImage RegionIntersection RegionMeasure RegionMember RegionMemberFunction RegionMoment RegionNearest RegionNearestFunction RegionPlot RegionPlot3D RegionProduct RegionQ RegionResize RegionSize RegionSymmetricDifference RegionUnion RegionWithin RegisterExternalEvaluator RegularExpression Regularization RegularlySampledQ RegularPolygon ReIm ReImLabels ReImPlot ReImStyle Reinstall RelationalDatabase RelationGraph Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot RemoteAuthorizationCaching RemoteConnect RemoteConnectionObject RemoteFile RemoteRun RemoteRunProcess Remove RemoveAlphaChannel RemoveAsynchronousTask RemoveAudioStream RemoveBackground RemoveChannelListener RemoveChannelSubscribers Removed RemoveDiacritics RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RemoveUsers RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart RepairMesh Repeated RepeatedNull RepeatedString RepeatedTiming RepeatingElement Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated ReplicateLayer RequiredPhysicalQuantities Resampling ResamplingAlgorithmData ResamplingMethod Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask ReshapeLayer Residue ResizeLayer Resolve ResourceAcquire ResourceData ResourceFunction ResourceObject ResourceRegister ResourceRemove ResourceSearch ResourceSubmissionObject ResourceSubmit ResourceSystemBase ResourceUpdate ResponseForm Rest RestartInterval Restricted Resultant ResumePacket Return ReturnEntersInput ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnReceiptFunction ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseSort ReverseSortBy ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ RiemannXi Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightComposition RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity RollPitchYawAngles RollPitchYawMatrix RomanNumeral Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RSolveValue RudinShapiro RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulePlot RulerUnits Run RunProcess RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilaritySameQ SameTest SampledEntityClass SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SASTriangle SatelliteData SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveConnection SaveDefinitions SavitzkyGolayMatrix SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTask ScheduledTaskActiveQ ScheduledTaskInformation ScheduledTaskInformationData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScientificNotationThreshold ScorerGi ScorerGiPrime ScorerHi ScorerHiPrime ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptForm ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition SearchAdjustment SearchIndexObject SearchIndices SearchQueryString SearchResultObject Sec Sech SechDistribution SecondOrderConeOptimization SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SecuredAuthenticationKey SecuredAuthenticationKeys SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook SelectFirst Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemanticImport SemanticImportString SemanticInterpretation SemialgebraicComponentInstances SemidefiniteOptimization SendMail SendMessage Sequence SequenceAlignment SequenceAttentionLayer SequenceCases SequenceCount SequenceFold SequenceFoldList SequenceForm SequenceHold SequenceLastLayer SequenceMostLayer SequencePosition SequencePredict SequencePredictorFunction SequenceReplace SequenceRestLayer SequenceReverseLayer SequenceSplit Series SeriesCoefficient SeriesData ServiceConnect ServiceDisconnect ServiceExecute ServiceObject ServiceRequest ServiceResponse ServiceSubmit SessionSubmit SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetCloudDirectory SetCookies SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPermissions SetPrecision SetProperty SetSecuredAuthenticationKey SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemModel SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetUsers SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share SharingList Sharpen ShearingMatrix ShearingTransform ShellRegion ShenCastanMatrix ShiftedGompertzDistribution ShiftRegisterSequence Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortTimeFourier ShortTimeFourierData ShortUpArrow Show ShowAutoConvert ShowAutoSpellCheck ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowCodeAssist ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiderealTime SiegelTheta SiegelTukeyTest SierpinskiCurve SierpinskiMesh Sign Signature SignedRankTest SignedRegionDistance SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ SimplePolygonQ SimplePolyhedronQ Simplex Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution SkinStyle Skip SliceContourPlot3D SliceDensityPlot3D SliceDistribution SliceVectorPlot3D Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDecomposition SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SnDispersion Snippet SnubPolyhedron SocialMediaData Socket SocketConnect SocketListen SocketListener SocketObject SocketOpen SocketReadMessage SocketReadyQ Sockets SocketWaitAll SocketWaitNext SoftmaxLayer SokalSneathDissimilarity SolarEclipse SolarSystemFeatureData SolidAngle SolidData SolidRegionQ Solve SolveAlways SolveDelayed Sort SortBy SortedBy SortedEntityClass Sound SoundAndGraphics SoundNote SoundVolume SourceLink Sow Space SpaceCurveData SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution SpatialMedian SpatialTransformationLayer Speak SpeakTextPacket SpearmanRankTest SpearmanRho SpeciesData SpecificityGoal SpectralLineData Spectrogram SpectrogramArray Specularity SpeechRecognize SpeechSynthesize SpellingCorrection SpellingCorrectionList SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SpherePoints SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SphericalShell SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquareMatrixQ SquareRepeatingElement SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave SSSTriangle StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackedDateListPlot StackedListPlot StackInhibit StadiumShape StandardAtmosphereData StandardDeviation StandardDeviationFilter StandardForm Standardize Standardized StandardOceanData StandbyDistribution Star StarClusterData StarData StarGraph StartAsynchronousTask StartExternalSession StartingStepSize StartOfLine StartOfString StartProcess StartScheduledTask StartupSound StartWebSession StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StateTransformationLinearize StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StereochemistryElements StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StoppingPowerData StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamMarkers StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringContainsQ StringCount StringDelete StringDrop StringEndsQ StringExpression StringExtract StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPadLeft StringPadRight StringPart StringPartition StringPosition StringQ StringRepeat StringReplace StringReplaceList StringReplacePart StringReverse StringRiffle StringRotateLeft StringRotateRight StringSkeleton StringSplit StringStartsQ StringTake StringTemplate StringToByteArray StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleData StyleDefinitions StyleForm StyleHints StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subdivide Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subsequences Subset SubsetEqual SubsetMap SubsetQ Subsets SubStar SubstitutionSystem Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubtractSides SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde Success SuchThat Sum SumConvergence SummationLayer Sunday SunPosition Sunrise Sunset SuperDagger SuperMinus SupernovaData SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceArea SurfaceColor SurfaceData SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricKey SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Synonyms Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SynthesizeMissingValues SystemDialogInput SystemException SystemGet SystemHelpPath SystemInformation SystemInformationData SystemInstall SystemModel SystemModeler SystemModelExamples SystemModelLinearize SystemModelParametricSimulate SystemModelPlot SystemModelProgressReporting SystemModelReliability SystemModels SystemModelSimulate SystemModelSimulateSensitivity SystemModelSimulationData SystemOpen SystemOptions SystemProcessData SystemProcesses SystemsConnectionsModel SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelLinearity SystemsModelMerge SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemsModelVectorRelativeOrders SystemStub SystemTestTab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TableViewBoxBackground TableViewBoxOptions TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeDrop TakeLargest TakeLargestBy TakeList TakeSmallest TakeSmallestBy TakeWhile Tally Tan Tanh TargetDevice TargetFunctions TargetSystem TargetUnits TaskAbort TaskExecute TaskObject TaskRemove TaskResume Tasks TaskSuspend TaskWait TautologyQ TelegraphProcess TemplateApply TemplateArgBox TemplateBox TemplateBoxOptions TemplateEvaluate TemplateExpression TemplateIf TemplateObject TemplateSequence TemplateSlot TemplateSlotSequence TemplateUnevaluated TemplateVerbatim TemplateWith TemporalData TemporalRegularity Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge TestID TestReport TestReportObject TestResultObject Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCases TextCell TextClipboardType TextContents TextData TextElement TextForm TextGrid TextJustification TextLine TextPacket TextParagraph TextPosition TextRecognize TextSearch TextSearchReport TextSentences TextString TextStructure TextStyle TextTranslation Texture TextureCoordinateFunction TextureCoordinateScaling TextWords Therefore ThermodynamicData ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreadingLayer ThreeJSymbol Threshold Through Throw ThueMorse Thumbnail Thursday Ticks TicksStyle TideData Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint TimeDirection TimeFormat TimeGoal TimelinePlot TimeObject TimeObjectQ Times TimesBy TimeSeries TimeSeriesAggregate TimeSeriesForecast TimeSeriesInsert TimeSeriesInvertibility TimeSeriesMap TimeSeriesMapThread TimeSeriesModel TimeSeriesModelFit TimeSeriesResample TimeSeriesRescale TimeSeriesShift TimeSeriesThread TimeSeriesWindow TimeUsed TimeValue TimeWarpingCorrespondence TimeWarpingDistance TimeZone TimeZoneConvert TimeZoneOffset Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate Today ToDiscreteTimeModel ToEntity ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase Tomorrow ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform ToPolarCoordinates TopologicalSort ToRadicals ToRules ToSphericalCoordinates ToString Total TotalHeight TotalLayer TotalVariationFilter TotalWidth TouchPosition TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TrackingFunction TracyWidomDistribution TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TrainingProgressCheckpointing TrainingProgressFunction TrainingProgressMeasurements TrainingProgressReporting TrainingStoppingCriterion TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationClass TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField TransformedProcess TransformedRegion TransitionDirection TransitionDuration TransitionEffect TransitiveClosureGraph TransitiveReductionGraph Translate TranslationOptions TranslationTransform Transliterate Transparent TransparentColor Transpose TransposeLayer TrapSelection TravelDirections TravelDirectionsData TravelDistance TravelDistanceList TravelMethod TravelTime TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle Triangle TriangleCenter TriangleConstruct TriangleMeasurement TriangleWave TriangularDistribution TriangulateMesh Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean TrimmedVariance TropicalStormData True TrueQ TruncatedDistribution TruncatedPolyhedron TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBoxOptions TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow TunnelData Tuples TuranGraph TuringMachine TuttePolynomial TwoWayRule Typed TypeSpecifierUnateQ Uncompress UnconstrainedParameters Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UnderseaFeatureData UndirectedEdge UndirectedGraph UndirectedGraphQ UndoOptions UndoTrackedVariables Unequal UnequalTo Unevaluated UniformDistribution UniformGraphDistribution UniformPolyhedron UniformSumDistribution Uninstall Union UnionPlus Unique UnitaryMatrixQ UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitSystem UnitTriangle UnitVector UnitVectorLayer UnityDimensions UniverseModelData UniversityData UnixTime Unprotect UnregisterExternalEvaluator UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpdateSearchIndex UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize UpperTriangularMatrixQ Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpTo UpValues URL URLBuild URLDecode URLDispatcher URLDownload URLDownloadSubmit URLEncode URLExecute URLExpand URLFetch URLFetchAsynchronous URLParse URLQueryDecode URLQueryEncode URLRead URLResponseTime URLSave URLSaveAsynchronous URLShorten URLSubmit UseGraphicsRange UserDefinedWavelet Using UsingFrontEnd UtilityFunctionV2Get ValenceErrorHandling ValidationLength ValidationSet Value ValueBox ValueBoxOptions ValueDimensions ValueForm ValuePreprocessingFunction ValueQ Values ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorAround VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorGreater VectorGreaterEqual VectorLess VectorLessEqual VectorMarkers VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerificationTest VerifyConvergence VerifyDerivedKey VerifyDigitalSignature VerifyInterpretation VerifySecurityCertificates VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexContract VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight VertexWeightedGraphQ Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewProjection ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoiceStyleData VoigtDistribution VolcanoData Volume VonMisesDistribution VoronoiMeshWaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WarpingCorrespondence WarpingDistance WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeatherForecastData WebAudioSearch WebElementObject WeberE WebExecute WebImage WebImageSearch WebSearch WebSessionObject WebSessions WebWindowObject Wedge Wednesday WeibullDistribution WeierstrassE1 WeierstrassE2 WeierstrassE3 WeierstrassEta1 WeierstrassEta2 WeierstrassEta3 WeierstrassHalfPeriods WeierstrassHalfPeriodW1 WeierstrassHalfPeriodW2 WeierstrassHalfPeriodW3 WeierstrassInvariantG2 WeierstrassInvariantG3 WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White WhiteNoiseProcess WhitePoint Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WikipediaData WikipediaSearch WilksW WilksWTest WindDirectionData WindingCount WindingPolygon WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowPersistentStyles WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth WindSpeedData WindVectorData WinsorizedMean WinsorizedVariance WishartMatrixDistribution With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult WolframLanguageData Word WordBoundary WordCharacter WordCloud WordCount WordCounts WordData WordDefinition WordFrequency WordFrequencyData WordList WordOrientation WordSearch WordSelectionFunction WordSeparators WordSpacings WordStem WordTranslation WorkingPrecision WrapAround Write WriteLine WriteString WronskianXMLElement XMLObject XMLTemplate Xnor Xor XYZColorYellow Yesterday YuleDissimilarityZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZIPCodeData ZipfDistribution ZoomCenter ZoomFactor ZTest ZTransform$Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AllowExternalChannelFunctions $AssertFunction $Assumptions $AsynchronousTask $AudioInputDevices $AudioOutputDevices $BaseDirectory $BatchInput $BatchOutput $BlockchainBase $BoxForms $ByteOrdering $CacheBaseDirectory $Canceled $ChannelBase $CharacterEncoding $CharacterEncodings $CloudBase $CloudConnected $CloudCreditsAvailable $CloudEvaluation $CloudExpressionBase $CloudObjectNameFormat $CloudObjectURLType $CloudRootDirectory $CloudSymbolBase $CloudUserID $CloudUserUUID $CloudVersion $CloudVersionNumber $CloudWolframEngineVersionNumber $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $Cookies $CookieStore $CreationDate $CurrentLink $CurrentTask $CurrentWebSession $DateStringFormat $DefaultAudioInputDevice $DefaultAudioOutputDevice $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultLocalBase $DefaultMailbox $DefaultNetworkInterface $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $EmbedCodeEnvironments $EmbeddableServices $EntityStores $Epilog $EvaluationCloudBase $EvaluationCloudObject $EvaluationEnvironment $ExportFormats $Failed $FinancialDataSource $FontFamilies $FormatType $FrontEnd $FrontEndSession $GeoEntityTypes $GeoLocation $GeoLocationCity $GeoLocationCountry $GeoLocationPrecision $GeoLocationSource $HistoryLength $HomeDirectory $HTMLExportRules $HTTPCookies $HTTPRequest $IgnoreEOF $ImageFormattingWidth $ImagingDevice $ImagingDevices $ImportFormats $IncomingMailSettings $InitialDirectory $Initialization $InitializationContexts $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $InterpreterTypes $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $LocalBase $LocalSymbolBase $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $MobilePhone $ModuleNumber $NetworkConnected $NetworkInterfaces $NetworkLicense $NewMessage $NewSymbol $Notebooks $NoValue $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $Permissions $PermissionsGroupBase $PersistenceBase $PersistencePath $PipeSupported $PlotTheme $Post $Pre $PreferencesDirectory $PreInitialization $PrePrint $PreRead $PrintForms $PrintLiteral $Printout3DPreviewer $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $PublisherID $RandomState $RecursionLimit $RegisteredDeviceClasses $RegisteredUserName $ReleaseNumber $RequesterAddress $RequesterWolframID $RequesterWolframUUID $ResourceSystemBase $RootDirectory $ScheduledTask $ScriptCommandLine $ScriptInputString $SecuredAuthenticationKeyTokens $ServiceCreditsAvailable $Services $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SourceLink $SSHAuthentication $SummaryBoxDataSizeLimit $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemMemory $SystemShell $SystemTimeZone $SystemWordLength $TemplatePath $TemporaryDirectory $TemporaryPrefix $TestFileName $TextStyle $TimedOut $TimeUnit $TimeZone $TimeZoneEntity $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $UnitSystem $Urgent $UserAddOnsDirectory $UserAgentLanguages $UserAgentMachine $UserAgentName $UserAgentOperatingSystem $UserAgentString $UserAgentVersion $UserBaseDirectory $UserDocumentsDirectory $Username $UserName $UserURLBase $Version $VersionNumber $VoiceStyles $WolframID $WolframUUID",
+contains:[b]},{begin:"^"+a.UNDERSCORE_IDENT_RE+"\\s*(?=[:+?]?=)"},{className:"meta",begin:/^\.PHONY:/,end:/$/,keywords:{"meta-keyword":".PHONY"},lexemes:/[\.\w]+/},{className:"section",begin:/^[^\s]+:/,end:/$/,contains:[b]}]}});b.registerLanguage("mathematica",function(a){return{aliases:["mma","wl"],lexemes:"(\\$|\\b)"+a.IDENT_RE+"\\b",keywords:"AASTriangle AbelianGroup Abort AbortKernels AbortProtect AbortScheduledTask Above Abs AbsArg AbsArgPlot Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AcceptanceThreshold AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Activate Active ActiveClassification ActiveClassificationObject ActiveItem ActivePrediction ActivePredictionObject ActiveStyle AcyclicGraphQ AddOnHelpPath AddSides AddTo AddToSearchIndex AddUsers AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AdministrativeDivisionData AffineHalfSpace AffineSpace AffineStateSpaceModel AffineTransform After AggregatedEntityClass AggregationLayer AircraftData AirportData AirPressureData AirTemperatureData AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowAdultContent AllowedCloudExtraParameters AllowedCloudParameterExtensions AllowedDimensions AllowedFrequencyRange AllowedHeads AllowGroupClose AllowIncomplete AllowInlineCells AllowKernelInitialization AllowLooseGrammar AllowReverseGroupClose AllowScriptLevelChange AllTrue Alphabet AlphabeticOrder AlphabeticSort AlphaChannel AlternateImage AlternatingFactorial AlternatingGroup AlternativeHypothesis Alternatives AltitudeMethod AmbientLight AmbiguityFunction AmbiguityList Analytic AnatomyData AnatomyForm AnatomyPlot3D AnatomySkinStyle AnatomyStyling AnchoredSearch And AndersonDarlingTest AngerJ AngleBisector AngleBracket AnglePath AnglePath3D AngleVector AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning AnimationRunTime AnimationTimeIndex Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotate Annotation AnnotationDelete AnnotationNames AnnotationRules AnnotationValue Annuity AnnuityDue Annulus AnomalyDetection AnomalyDetectorFunction Anonymous Antialiasing AntihermitianMatrixQ Antisymmetric AntisymmetricMatrixQ Antonyms AnyOrder AnySubset AnyTrue Apart ApartSquareFree APIFunction Appearance AppearanceElements AppearanceRules AppellF1 Append AppendCheck AppendLayer AppendTo ApplicationIdentificationKey Apply ApplySides ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcCurvature ARCHProcess ArcLength ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Area Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess Around AroundReplace ARProcess Array ArrayComponents ArrayDepth ArrayFilter ArrayFlatten ArrayMesh ArrayPad ArrayPlot ArrayQ ArrayResample ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads ASATriangle Ask AskAppend AskConfirm AskDisplay AskedQ AskedValue AskFunction AskState AskTemplateDisplay AspectRatio AspectRatioFixed Assert AssociateTo Association AssociationFormat AssociationMap AssociationQ AssociationThread AssumeDeterministic Assuming Assumptions AstronomicalData AsymptoticDSolveValue AsymptoticEqual AsymptoticEquivalent AsymptoticGreater AsymptoticGreaterEqual AsymptoticIntegrate AsymptoticLess AsymptoticLessEqual AsymptoticOutputTracker AsymptoticRSolveValue AsymptoticSolve AsymptoticSum Asynchronous AsynchronousTaskObject AsynchronousTasks Atom AtomCoordinates AtomCount AtomDiagramCoordinates AtomList AtomQ AttentionLayer Attributes Audio AudioAmplify AudioAnnotate AudioAnnotationLookup AudioBlockMap AudioCapture AudioChannelAssignment AudioChannelCombine AudioChannelMix AudioChannels AudioChannelSeparate AudioData AudioDelay AudioDelete AudioDevice AudioDistance AudioFade AudioFrequencyShift AudioGenerator AudioIdentify AudioInputDevice AudioInsert AudioIntervals AudioJoin AudioLabel AudioLength AudioLocalMeasurements AudioLooping AudioLoudness AudioMeasurements AudioNormalize AudioOutputDevice AudioOverlay AudioPad AudioPan AudioPartition AudioPause AudioPitchShift AudioPlay AudioPlot AudioQ AudioRecord AudioReplace AudioResample AudioReverb AudioSampleRate AudioSpectralMap AudioSpectralTransformation AudioSplit AudioStop AudioStream AudioStreams AudioTimeStretch AudioTrim AudioType AugmentedPolyhedron AugmentedSymmetricPolynomial Authenticate Authentication AuthenticationDialog AutoAction Autocomplete AutocompletionFunction AutoCopy AutocorrelationTest AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutoQuoteCharacters AutoRefreshed AutoRemove AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords AutoSubmitting Axes AxesEdge AxesLabel AxesOrigin AxesStyle AxiomaticTheory AxisBabyMonsterGroupB Back Background BackgroundAppearance BackgroundTasksSettings Backslash Backsubstitution Backward Ball Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarcodeImage BarcodeRecognize BaringhausHenzeTest BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseDecode BaseEncode BaseForm Baseline BaselinePosition BaseStyle BasicRecurrentLayer BatchNormalizationLayer BatchSize BatesDistribution BattleLemarieWavelet BayesianMaximization BayesianMaximizationObject BayesianMinimization BayesianMinimizationObject Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized Between BetweennessCentrality BeveledPolyhedron BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryDeserialize BinaryDistance BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinarySerialize BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BiquadraticFilterModel BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor BiweightLocation BiweightMidvariance Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockchainAddressData BlockchainBase BlockchainBlockData BlockchainContractValue BlockchainData BlockchainGet BlockchainKeyEncode BlockchainPut BlockchainTokenData BlockchainTransaction BlockchainTransactionData BlockchainTransactionSign BlockchainTransactionSubmit BlockMap BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bond BondCount BondList BondQ Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms BooleanQ BooleanRegion Booleans BooleanStrings BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryDiscretizeGraphics BoundaryDiscretizeRegion BoundaryMesh BoundaryMeshRegion BoundaryMeshRegionQ BoundaryStyle BoundedRegionQ BoundingRegion Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxObject BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break BridgeData BrightnessEqualize BroadcastStationData Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurve3DBoxOptions BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BSplineSurface3DBoxOptions BubbleChart BubbleChart3D BubbleScale BubbleSizes BuildingData BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteArray ByteArrayFormat ByteArrayQ ByteArrayToString ByteCount ByteOrderingC CachedValue CacheGraphics CachePersistence CalendarConvert CalendarData CalendarType Callout CalloutMarker CalloutStyle CallPacket CanberraDistance Cancel CancelButton CandlestickChart CanonicalGraph CanonicalizePolygon CanonicalizePolyhedron CanonicalName CanonicalWarpingCorrespondence CanonicalWarpingDistance CantorMesh CantorStaircase Cap CapForm CapitalDifferentialD Capitalize CapsuleShape CaptureRunning CardinalBSplineBasis CarlemanLinearize CarmichaelLambda CaseOrdering Cases CaseSensitive Cashflow Casoratian Catalan CatalanNumber Catch Catenate CatenateLayer CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling CelestialSystem Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEvaluationLanguage CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellLabelStyle CellLabelTemplate CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterArray CenterDot CentralFeature CentralMoment CentralMomentGeneratingFunction Cepstrogram CepstrogramArray CepstrumArray CForm ChampernowneNumber ChangeOptions ChannelBase ChannelBrokerAction ChannelDatabin ChannelHistoryLength ChannelListen ChannelListener ChannelListeners ChannelListenerWait ChannelObject ChannelPreSendFunction ChannelReceiverFunction ChannelSend ChannelSubscribers ChanVeseBinarize Character CharacterCounts CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterName CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop ChromaticityPlot ChromaticityPlot3D ChromaticPolynomial Circle CircleBox CircleDot CircleMinus CirclePlus CirclePoints CircleThrough CircleTimes CirculantGraph CircularOrthogonalMatrixDistribution CircularQuaternionMatrixDistribution CircularRealMatrixDistribution CircularSymplecticMatrixDistribution CircularUnitaryMatrixDistribution Circumsphere CityData ClassifierFunction ClassifierInformation ClassifierMeasurements ClassifierMeasurementsObject Classify ClassPriors Clear ClearAll ClearAttributes ClearCookies ClearPermissions ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipPlanesStyle ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent CloudAccountData CloudBase CloudConnect CloudDeploy CloudDirectory CloudDisconnect CloudEvaluate CloudExport CloudExpression CloudExpressions CloudFunction CloudGet CloudImport CloudLoggingData CloudObject CloudObjectInformation CloudObjectInformationData CloudObjectNameFormat CloudObjects CloudObjectURLType CloudPublish CloudPut CloudRenderingMethod CloudSave CloudShare CloudSubmit CloudSymbol CloudUnshare ClusterClassify ClusterDissimilarityFunction ClusteringComponents ClusteringTree CMYKColor Coarse CodeAssistOptions Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorBalance ColorCombine ColorConvert ColorCoverage ColorData ColorDataFunction ColorDetect ColorDistance ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQ ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorsNear ColorSpace ColorToneMapping Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CombinedEntityClass CombinerFunction CometData CommonDefaultFormatTypes Commonest CommonestFilter CommonName CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompanyData CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledCodeFunction CompiledFunction CompilerOptions Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComplexListPlot ComplexPlot ComplexPlot3D ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries CompositeQ Composition CompoundElement CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData ComputeUncertainty Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath ConformAudio ConformImages Congruent ConicHullRegion ConicHullRegion3DBox ConicHullRegionBox ConicOptimization Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphComponents ConnectedGraphQ ConnectedMeshComponents ConnectedMoleculeComponents ConnectedMoleculeQ ConnectionSettings ConnectLibraryCallbackFunction ConnectSystemModelComponents ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray ConstantArrayLayer ConstantImage ConstantPlusLayer ConstantRegionQ Constants ConstantTimesLayer ConstellationData ConstrainedMax ConstrainedMin Construct Containing ContainsAll ContainsAny ContainsExactly ContainsNone ContainsOnly ContentFieldOptions ContentLocationFunction ContentObject ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTask ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean ContrastiveLossLayer Control ControlActive ControlAlignment ControlGroupContentsBox ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket ConvexHullMesh ConvexPolygonQ ConvexPolyhedronQ ConvolutionLayer Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CookieFunction Cookies CoordinateBoundingBox CoordinateBoundingBoxArray CoordinateBounds CoordinateBoundsArray CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDatabin CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CountDistinct CountDistinctBy CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Counts CountsBy Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateCellID CreateChannel CreateCloudExpression CreateDatabin CreateDataSystemModel CreateDialog CreateDirectory CreateDocument CreateFile CreateIntermediateDirectories CreateManagedLibraryExpression CreateNotebook CreatePalette CreatePalettePacket CreatePermissionsGroup CreateScheduledTask CreateSearchIndex CreateSystemModel CreateTemporary CreateUUID CreateWindow CriterionFunction CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossEntropyLossLayer CrossingCount CrossingDetect CrossingPolygon CrossMatrix Csc Csch CTCLossLayer Cube CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrencyConvert CurrentDate CurrentImage CurrentlySpeakingPacket CurrentNotebookImage CurrentScreenImage CurrentValue Curry CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecompositionD DagumDistribution DamData DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DatabaseConnect DatabaseDisconnect DatabaseReference Databin DatabinAdd DatabinRemove Databins DatabinUpload DataCompression DataDistribution DataRange DataReversed Dataset Date DateBounds Dated DateDelimiters DateDifference DatedUnit DateFormat DateFunction DateHistogram DateList DateListLogPlot DateListPlot DateListStepPlot DateObject DateObjectQ DateOverlapsQ DatePattern DatePlus DateRange DateReduction DateString DateTicksFormat DateValue DateWithinQ DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayHemisphere DaylightQ DayMatchQ DayName DayNightTerminator DayPlus DayRange DayRound DeBruijnGraph DeBruijnSequence Debug DebugTag Decapitalize Decimal DecimalForm DeclareKnownSymbols DeclarePackage Decompose DeconvolutionLayer Decrement Decrypt DecryptFile DedekindEta DeepSpaceProbeData Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultPrintPrecision DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValue DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod DefineResourceFunction Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic DEigensystem DEigenvalues Deinitialization Del DelaunayMesh Delayed Deletable Delete DeleteAnomalies DeleteBorderComponents DeleteCases DeleteChannel DeleteCloudExpression DeleteContents DeleteDirectory DeleteDuplicates DeleteDuplicatesBy DeleteFile DeleteMissing DeleteObject DeletePermissionsKey DeleteSearchIndex DeleteSmallComponents DeleteStopwords DeleteWithContents DeletionWarning DelimitedArray DelimitedSequence Delimiter DelimiterFlashTime DelimiterMatching Delimiters DeliveryFunction Dendrogram Denominator DensityGraphics DensityHistogram DensityPlot DensityPlot3D DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DerivedKey DescriptorStateSpace DesignMatrix DestroyAfterEvaluation Det DeviceClose DeviceConfigure DeviceExecute DeviceExecuteAsynchronous DeviceObject DeviceOpen DeviceOpenQ DeviceRead DeviceReadBuffer DeviceReadLatest DeviceReadList DeviceReadTimeSeries Devices DeviceStreams DeviceWrite DeviceWriteBuffer DGaussianWavelet DiacriticalPositioning Diagonal DiagonalizableMatrixQ DiagonalMatrix DiagonalMatrixQ Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DictionaryWordQ DifferenceDelta DifferenceOrder DifferenceQuotient DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitalSignature DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralAngle DihedralGroup Dilation DimensionalCombinations DimensionalMeshComponents DimensionReduce DimensionReducerFunction DimensionReduction Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletBeta DirichletCharacter DirichletCondition DirichletConvolve DirichletDistribution DirichletEta DirichletL DirichletLambda DirichletTransform DirichletWindow DisableConsolePrintPacket DisableFormatting DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLimit DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscreteMaxLimit DiscreteMinLimit DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform DiscretizeGraphics DiscretizeRegion Discriminant DisjointQ Disjunction Disk DiskBox DiskMatrix DiskSegment Dispatch DispatchQ DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceMatrix DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers DivideSides Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentGenerator DocumentGeneratorInformation DocumentGeneratorInformationData DocumentGenerators DocumentNotebook DocumentWeightingRules Dodecahedron DomainRegistrationInformation DominantColors DOSTextFormat Dot DotDashed DotEqual DotLayer DotPlusLayer Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DropoutLayer DSolve DSolveValue Dt DualLinearProgramming DualPolyhedron DualSystemsModel DumpGet DumpSave DuplicateFreeQ Duration Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicGeoGraphics DynamicImage DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptionsE EarthImpactData EarthquakeData EccentricityCentrality Echo EchoFunction EclipseType EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeContract EdgeCost EdgeCount EdgeCoverQ EdgeCycleMatrix EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight EdgeWeightedGraphQ Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData ElementwiseLayer ElidedForms Eliminate EliminationOrder Ellipsoid EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmbedCode EmbeddedHTML EmbeddedService EmbeddingLayer EmbeddingObject EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EmptyRegion EnableConsolePrintPacket Enabled Encode Encrypt EncryptedObject EncryptFile End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfBuffer EndOfFile EndOfLine EndOfString EndPackage EngineEnvironment EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entity EntityClass EntityClassList EntityCopies EntityFunction EntityGroup EntityInstance EntityList EntityPrefetch EntityProperties EntityProperty EntityPropertyClass EntityRegister EntityStore EntityStores EntityTypeName EntityUnregister EntityValue Entropy EntropyFilter Environment Epilog EpilogFunction Equal EqualColumns EqualRows EqualTilde EqualTo EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EscapeRadius EstimatedBackground EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerAngles EulerCharacteristic EulerE EulerGamma EulerianGraphQ EulerMatrix EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluateScheduledTask EvaluationBox EvaluationCell EvaluationCompletionAction EvaluationData EvaluationElements EvaluationEnvironment EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels EventSeries ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludedLines ExcludedPhysicalQuantities ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog ExoplanetData Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi ExpirationDate Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportByteArray ExportForm ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpressionUUID ExpToTrig ExtendedEntityClass ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalBundle ExternalCall ExternalDataCharacterEncoding ExternalEvaluate ExternalFunction ExternalFunctionName ExternalObject ExternalOptions ExternalSessionObject ExternalSessions ExternalTypeSignature ExternalValue Extract ExtractArchive ExtractLayer ExtremeValueDistributionFaceForm FaceGrids FaceGridsStyle FacialFeatures Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail Failure FailureAction FailureDistribution FailureQ False FareySequence FARIMAProcess FeatureDistance FeatureExtract FeatureExtraction FeatureExtractor FeatureExtractorFunction FeatureNames FeatureNearest FeatureSpacePlot FeatureSpacePlot3D FeatureTypes FEDisableConsolePrintPacket FeedbackLinearize FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket FetalGrowthData Fibonacci Fibonorial FieldCompletionFunction FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileConvert FileDate FileExistsQ FileExtension FileFormat FileHandler FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameForms FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileSize FileSystemMap FileSystemScan FileTemplate FileTemplateApply FileType FilledCurve FilledCurveBox FilledCurveBoxOptions Filling FillingStyle FillingTransform FilteredEntityClass FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindAnomalies FindArgMax FindArgMin FindChannels FindClique FindClusters FindCookies FindCurvePath FindCycle FindDevices FindDistribution FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEdgeIndependentPaths FindEquationalProof FindEulerianCycle FindExternalEvaluators FindFaces FindFile FindFit FindFormula FindFundamentalCycles FindGeneratingFunction FindGeoLocation FindGeometricConjectures FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindHamiltonianPath FindHiddenMarkovStates FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMatchingColor FindMaximum FindMaximumFlow FindMaxValue FindMeshDefects FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindMoleculeSubstructure FindPath FindPeaks FindPermutation FindPostmanTour FindProcessParameters FindRepeat FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindSpanningTree FindSystemModelEquilibrium FindTextualAnswer FindThreshold FindTransientRepeat FindVertexCover FindVertexCut FindVertexIndependentPaths Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstCase FirstPassageTimeDistribution FirstPosition FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FitRegularization FittedModel FixedOrder FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlattenLayer FlatTopWindow FlipView Floor FlowPolynomial FlushPrintOutputPacket Fold FoldList FoldPair FoldPairList FollowRedirects Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FormControl FormFunction FormLayoutFunction FormObject FormPage FormTheme FormulaData FormulaLookup FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalGaussianNoiseProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameRate FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrenetSerretSystem FrequencySamplingFilterKernel FresnelC FresnelF FresnelG FresnelS Friday FrobeniusNumber FrobeniusSolve FromAbsoluteTime FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS FromEntity FromJulianDate FromLetterNumber FromPolarCoordinates FromRomanNumeral FromSphericalCoordinates FromUnixTime Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullInformationOutputRegulator FullOptions FullRegion FullSimplify Function FunctionCompile FunctionCompileExport FunctionCompileExportByteArray FunctionCompileExportLibrary FunctionCompileExportString FunctionDomain FunctionExpand FunctionInterpolation FunctionPeriod FunctionRange FunctionSpace FussellVeselyImportanceGaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins GalaxyData GalleryView Gamma GammaDistribution GammaRegularized GapPenalty GARCHProcess GatedRecurrentLayer Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianOrthogonalMatrixDistribution GaussianSymplecticMatrixDistribution GaussianUnitaryMatrixDistribution GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateAsymmetricKeyPair GenerateConditions GeneratedCell GeneratedDocumentBinding GenerateDerivedKey GenerateDigitalSignature GenerateDocument GeneratedParameters GeneratedQuantityMagnitudes GenerateHTTPResponse GenerateSecuredAuthenticationKey GenerateSymmetricKey GeneratingFunction GeneratorDescription GeneratorHistoryLength GeneratorOutputType Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeoAntipode GeoArea GeoArraySize GeoBackground GeoBoundingBox GeoBounds GeoBoundsRegion GeoBubbleChart GeoCenter GeoCircle GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDisk GeoDisplacement GeoDistance GeoDistanceList GeoElevationData GeoEntities GeoGraphics GeogravityModelData GeoGridDirectionDifference GeoGridLines GeoGridLinesStyle GeoGridPosition GeoGridRange GeoGridRangePadding GeoGridUnitArea GeoGridUnitDistance GeoGridVector GeoGroup GeoHemisphere GeoHemisphereBoundary GeoHistogram GeoIdentify GeoImage GeoLabels GeoLength GeoListPlot GeoLocation GeologicalPeriodData GeomagneticModelData GeoMarker GeometricAssertion GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricScene GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoModel GeoNearest GeoPath GeoPosition GeoPositionENU GeoPositionXYZ GeoProjection GeoProjectionData GeoRange GeoRangePadding GeoRegionValuePlot GeoResolution GeoScaleBar GeoServer GeoSmoothHistogram GeoStreamPlot GeoStyling GeoStylingImageFunction GeoVariant GeoVector GeoVectorENU GeoVectorPlot GeoVectorXYZ GeoVisibleRegion GeoVisibleRegionBoundary GeoWithinQ GeoZoomLevel GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenAngle GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter GrammarApply GrammarRules GrammarToken Graph Graph3D GraphAssortativity GraphAutomorphismGroup GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel Greater GreaterEqual GreaterEqualLess GreaterEqualThan GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterThan GreaterTilde Green GreenFunction Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupBy GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators Groupings GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain GroupTogetherGrouping GroupTogetherNestedGrouping GrowCutComponents Gudermannian GuidedFilter GumbelDistributionHaarWavelet HadamardMatrix HalfLine HalfNormalDistribution HalfPlane HalfSpace HamiltonianGraphQ HammingDistance HammingWindow HandlerFunctions HandlerFunctionsKeys HankelH1 HankelH2 HankelMatrix HankelTransform HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash Haversine HazardFunction Head HeadCompose HeaderLines Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings Here HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenMarkovProcess HiddenSurface Highlighted HighlightGraph HighlightImage HighlightMesh HighpassFilter HigmanSimsGroupHS HilbertCurve HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HistoricalPeriodData HitMissTransform HITSCentrality HjorthDistribution HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HostLookup HotellingTSquareDistribution HoytDistribution HTMLSave HTTPErrorResponse HTTPRedirect HTTPRequest HTTPRequestData HTTPResponse Hue HumanGrowthData HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyperplane Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestDataI IconData Iconize IconizedObject IconRules Icosahedron Identity IdentityMatrix If IgnoreCase IgnoreDiacritics IgnorePunctuation IgnoreSpellCheck IgnoringInactive Im Image Image3D Image3DProjection Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageApplyIndexed ImageAspectRatio ImageAssemble ImageAugmentationLayer ImageBoundingBoxes ImageCache ImageCacheValid ImageCapture ImageCaptureFunction ImageCases ImageChannels ImageClip ImageCollage ImageColorSpace ImageCompose ImageContainsQ ImageContents ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDisplacements ImageDistance ImageEffect ImageExposureCombine ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageFocusCombine ImageForestingComponents ImageFormattingWidth ImageForwardTransformation ImageGraphics ImageHistogram ImageIdentify ImageInstanceQ ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarker ImageMarkers ImageMeasurements ImageMesh ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImagePosition ImagePreviewFunction ImagePyramid ImagePyramidApply ImageQ ImageRangeCache ImageRecolor ImageReflect ImageRegion ImageResize ImageResolution ImageRestyle ImageRotate ImageRotated ImageSaliencyFilter ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions ImagingDevice ImplicitRegion Implies Import ImportAutoReplacements ImportByteArray ImportOptions ImportString ImprovementImportance In Inactivate Inactive IncidenceGraph IncidenceList IncidenceMatrix IncludeAromaticBonds IncludeConstantBasis IncludeDefinitions IncludeDirectories IncludeFileExtension IncludeGeneratorTasks IncludeHydrogens IncludeInflections IncludeMetaInformation IncludePods IncludeQuantities IncludeRelatedTables IncludeSingularTerm IncludeWindowTimes Increment IndefiniteMatrixQ Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentPhysicalQuantity IndependentUnit IndependentUnitDimension IndependentVertexSetQ Indeterminate IndeterminateThreshold IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers InfiniteLine InfinitePlane Infinity Infix InflationAdjust InflationMethod Information InformationData InformationDataGrid Inherited InheritScope InhomogeneousPoissonProcess InitialEvaluationHistory Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InitializationObjects InitializationValue Initialize InitialSeeding InlineCounterAssignments InlineCounterIncrements InlineRules Inner InnerPolygon InnerPolyhedron Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionFunction InsertionPointObject InsertLinebreaks InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Insphere Install InstallService InstanceNormalizationLayer InString Integer IntegerDigits IntegerExponent IntegerLength IntegerName IntegerPart IntegerPartitions IntegerQ IntegerReverse Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction Interpreter InterpretTemplate InterquartileRange Interrupt InterruptSettings IntersectingQ Intersection Interval IntervalIntersection IntervalMarkers IntervalMarkersStyle IntervalMemberQ IntervalSlider IntervalUnion Into Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHankelTransform InverseHaversine InverseImagePyramid InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InverseMellinTransform InversePermutation InverseRadon InverseRadonTransform InverseSeries InverseShortTimeFourier InverseSpectrogram InverseSurvivalFunction InverseTransformedRegion InverseWaveletTransform InverseWeierstrassP InverseWishartMatrixDistribution InverseZTransform Invisible InvisibleApplication InvisibleTimes IPAddress IrreduciblePolynomialQ IslandData IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemAspectRatio ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcessJaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join JoinAcross Joined JoinedCurve JoinedCurveBox JoinedCurveBoxOptions JoinForm JordanDecomposition JordanModelDecomposition JulianDate JuliaSetBoettcher JuliaSetIterationCount JuliaSetPlot JuliaSetPointsK KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KEdgeConnectedComponents KEdgeConnectedGraphQ KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelFunction KernelMixtureDistribution Kernels Ket Key KeyCollisionFunction KeyComplement KeyDrop KeyDropFrom KeyExistsQ KeyFreeQ KeyIntersection KeyMap KeyMemberQ KeypointStrength Keys KeySelect KeySort KeySortBy KeyTake KeyUnion KeyValueMap KeyValuePattern Khinchin KillProcess KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnapsackSolve KnightTourGraph KnotData KnownUnitQ KochCurve KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter KVertexConnectedComponents KVertexConnectedGraphQLABColor Label Labeled LabeledSlider LabelingFunction LabelingSize LabelStyle LabelVisibility LaguerreL LakeData LambdaComponents LambertW LaminaData LanczosWindow LandauDistribution Language LanguageCategory LanguageData LanguageIdentify LanguageOptions LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCHColor LCM LeaderSize LeafCount LeapYearQ LearnDistribution LearnedDistribution LearningRate LearningRateMultipliers LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessEqualThan LessFullEqual LessGreater LessLess LessSlantEqual LessThan LessTilde LetterCharacter LetterCounts LetterNumber LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryDataType LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox Line3DBoxOptions LinearFilter LinearFractionalOptimization LinearFractionalTransform LinearGradientImage LinearizingTransformationData LinearLayer LinearModelFit LinearOffsetFunction LinearOptimization LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBoxOptions LineBreak LinebreakAdjustments LineBreakChart LinebreakSemicolonWeighting LineBreakWithin LineColor LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRankCentrality LinkRead LinkReadHeld LinkReadyQ Links LinkService LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot ListDensityPlot3D Listen ListFormat ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListSliceContourPlot3D ListSliceDensityPlot3D ListSliceVectorPlot3D ListStepPlot ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalAdaptiveBinarize LocalCache LocalClusteringCoefficient LocalizeDefinitions LocalizeVariables LocalObject LocalObjects LocalResponseNormalizationLayer LocalSubmit LocalSymbol LocalTime LocalTimeZone LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogisticSigmoid LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongestOrderedSequence LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow LongShortTermMemoryLayer Lookup Loopback LoopFreeGraphQ LossFunction LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowerTriangularMatrixQ LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LunarEclipse LUVColor LyapunovSolve LyonsGroupLyMachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MailAddressValidation MailExecute MailFolder MailItem MailReceiverFunction MailResponseFunction MailSearch MailServerConnect MailServerConnection MailSettings MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules ManagedLibraryExpressionID ManagedLibraryExpressionQ MandelbrotSetBoettcher MandelbrotSetDistance MandelbrotSetIterationCount MandelbrotSetMemberQ MandelbrotSetPlot MangoldtLambda ManhattanDistance Manipulate Manipulator MannedSpaceMissionData MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarchenkoPasturDistribution MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicalFunctionData MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixNormalDistribution MatrixPlot MatrixPower MatrixPropertyDistribution MatrixQ MatrixRank MatrixTDistribution Max MaxBend MaxCellMeasure MaxColorDistance MaxDetect MaxDuration MaxExtraBandwidths MaxExtraConditions MaxFeatureDisplacement MaxFeatures MaxFilter MaximalBy Maximize MaxItems MaxIterations MaxLimit MaxMemoryUsed MaxMixtureKernels MaxOverlapFraction MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxTrainingRounds MaxValue MaxwellDistribution MaxWordGap McLaughlinGroupMcL Mean MeanAbsoluteLossLayer MeanAround MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter MeanSquaredLossLayer Median MedianDeviation MedianFilter MedicalTestData Medium MeijerG MeijerGReduce MeixnerDistribution MellinConvolve MellinTransform MemberQ MemoryAvailable MemoryConstrained MemoryConstraint MemoryInUse MengerMesh Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuList MenuPacket MenuSortingValue MenuStyle MenuView Merge MergeDifferences MergingFunction MersennePrimeExponent MersennePrimeExponentQ Mesh MeshCellCentroid MeshCellCount MeshCellHighlight MeshCellIndex MeshCellLabel MeshCellMarker MeshCellMeasure MeshCellQuality MeshCells MeshCellShapeFunction MeshCellStyle MeshCoordinates MeshFunctions MeshPrimitives MeshQualityGoal MeshRange MeshRefinementFunction MeshRegion MeshRegionQ MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageObject MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation MeteorShowerData Method MethodOptions MexicanHatWavelet MeyerWavelet Midpoint Min MinColorDistance MinDetect MineralData MinFilter MinimalBy MinimalPolynomial MinimalStateSpaceModel Minimize MinimumTimeIncrement MinIntervalSize MinkowskiQuestionMark MinLimit MinMax MinorPlanetData Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingBehavior MissingDataMethod MissingDataRules MissingQ MissingString MissingStyle MissingValuePattern MittagLefflerE MixedFractionParts MixedGraphQ MixedMagnitude MixedRadix MixedRadixQuantity MixedUnit MixtureDistribution Mod Modal Mode Modular ModularInverse ModularLambda Module Modulus MoebiusMu Molecule MoleculeContainsQ MoleculeEquivalentQ MoleculeGraph MoleculeModify MoleculePattern MoleculePlot MoleculePlot3D MoleculeProperty MoleculeQ MoleculeValue Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction MomentOfInertia Monday Monitor MonomialList MonomialOrder MonsterGroupM MoonPhase MoonPosition MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform MortalityData Most MountainData MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovieData MovingAverage MovingMap MovingMedian MoyalDistribution Multicolumn MultiedgeStyle MultigraphQ MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity MultiplySides Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistributionN NakagamiDistribution NameQ Names NamespaceBox NamespaceBoxOptions Nand NArgMax NArgMin NBernoulliB NBodySimulation NBodySimulationData NCache NDEigensystem NDEigenvalues NDSolve NDSolveValue Nearest NearestFunction NearestNeighborGraph NearestTo NebulaData NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeDefiniteMatrixQ NegativeIntegers NegativeMultinomialDistribution NegativeRationals NegativeReals NegativeSemidefiniteMatrixQ NeighborhoodData NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestGraph NestList NestWhile NestWhileList NetAppend NetBidirectionalOperator NetChain NetDecoder NetDelete NetDrop NetEncoder NetEvaluationMode NetExtract NetFlatten NetFoldOperator NetGraph NetInformation NetInitialize NetInsert NetInsertSharedArrays NetJoin NetMapOperator NetMapThreadOperator NetMeasurements NetModel NetNestOperator NetPairEmbeddingOperator NetPort NetPortGradient NetPrepend NetRename NetReplace NetReplacePart NetSharedArray NetStateObject NetTake NetTrain NetTrainResultsObject NetworkPacketCapture NetworkPacketRecording NetworkPacketRecordingDuring NetworkPacketTrace NeumannValue NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextCell NextDate NextPrime NextScheduledTaskTime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NightHemisphere NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants NondimensionalizationTransform None NoneTrue NonlinearModelFit NonlinearStateSpaceModel NonlocalMeansFilter NonNegative NonNegativeIntegers NonNegativeRationals NonNegativeReals NonPositive NonPositiveIntegers NonPositiveRationals NonPositiveReals Nor NorlundB Norm Normal NormalDistribution NormalGrouping NormalizationLayer Normalize Normalized NormalizedSquaredEuclideanDistance NormalMatrixQ NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookImport NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookTemplate NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde Nothing NotHumpDownHump NotHumpEqual NotificationFunction NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar Now NoWhitespace NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms NuclearExplosionData NuclearReactorData Null NullRecords NullSpace NullWords Number NumberCompose NumberDecompose NumberExpand NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberLinePlot NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumeratorDenominator NumericalOrder NumericalSort NumericArray NumericArrayQ NumericArrayType NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlotO ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OceanData Octahedron OddQ Off Offset OLEData On ONanGroupON Once OneIdentity Opacity OpacityFunction OpacityFunctionScaling Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionalElement OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering OrderingBy OrderingLayer Orderless OrderlessPatternSequence OrnsteinUhlenbeckProcess Orthogonalize OrthogonalMatrixQ Out Outer OuterPolygon OuterPolyhedron OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OverwriteTarget OwenT OwnValuesPackage PackingMethod PaddedForm Padding PaddingLayer PaddingSize PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageTheme PageWidth Pagination PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath PalindromeQ Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo Parallelepiped ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds Parallelogram ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParametricRegion ParentBox ParentCell ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParentNotebook ParetoDistribution ParetoPickandsDistribution ParkData Part PartBehavior PartialCorrelationFunction PartialD ParticleAcceleratorData ParticleData Partition PartitionGranularity PartitionsP PartitionsQ PartLayer PartOfSpeech PartProtection ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteAutoQuoteCharacters PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PeakDetect PeanoCurve PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PercentForm PerfectNumber PerfectNumberQ PerformanceGoal Perimeter PeriodicBoundaryCondition PeriodicInterpolation Periodogram PeriodogramArray Permanent Permissions PermissionsGroup PermissionsGroupMemberQ PermissionsGroups PermissionsKey PermissionsKeys PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PerpendicularBisector PersistenceLocation PersistenceTime PersistentObject PersistentObjects PersistentValue PersonData PERTDistribution PetersenGraph PhaseMargins PhaseRange PhysicalSystemData Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest PingTime Pink PitchRecognize Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarAngle PlanarGraph PlanarGraphQ PlanckRadiationLaw PlaneCurveData PlanetaryMoonData PlanetData PlantData Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLabels PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangeClipPlanesStyle PlotRangePadding PlotRegion PlotStyle PlotTheme Pluralize Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox Point3DBoxOptions PointBox PointBoxOptions PointFigureChart PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonalNumber PolygonAngle PolygonBox PolygonBoxOptions PolygonCoordinates PolygonDecomposition PolygonHoleScale PolygonIntersections PolygonScale Polyhedron PolyhedronAngle PolyhedronCoordinates PolyhedronData PolyhedronDecomposition PolyhedronGenus PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PoolingLayer PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position PositionIndex Positive PositiveDefiniteMatrixQ PositiveIntegers PositiveRationals PositiveReals PositiveSemidefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerRange PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement Predict PredictionRoot PredictorFunction PredictorInformation PredictorMeasurements PredictorMeasurementsObject PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependLayer PrependTo PreprocessingRules PreserveColor PreserveImageOptions Previous PreviousCell PreviousDate PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitivePolynomialQ PrimitiveRoot PrimitiveRootList PrincipalComponents PrincipalValue Print PrintableASCIIQ PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment Printout3D Printout3DPreviewer PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateKey PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessConnection ProcessDirectory ProcessEnvironment Processes ProcessEstimator ProcessInformation ProcessObject ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessStatus ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm ProofObject Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse PsychrometricPropertyData PublicKey PublisherID PulsarData PunctuationCharacter Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptionsQBinomial QFactorial QGamma QHypergeometricPFQ QnDispersion QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ QuadraticOptimization Quantile QuantilePlot Quantity QuantityArray QuantityDistribution QuantityForm QuantityMagnitude QuantityQ QuantityUnit QuantityVariable QuantityVariableCanonicalUnit QuantityVariableDimensions QuantityVariableIdentifier QuantityVariablePhysicalQuantity Quartics QuartileDeviation Quartiles QuartileSkewness Query QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainderRadialGradientImage RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RadonTransform RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Ramp Random RandomChoice RandomColor RandomComplex RandomEntity RandomFunction RandomGeoPosition RandomGraph RandomImage RandomInstance RandomInteger RandomPermutation RandomPoint RandomPolygon RandomPolyhedron RandomPrime RandomReal RandomSample RandomSeed RandomSeeding RandomVariate RandomWalkProcess RandomWord Range RangeFilter RangeSpecification RankedMax RankedMin RarerProbability Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadByteArray ReadLine ReadList ReadProtected ReadString Real RealAbs RealBlockDiagonalForm RealDigits RealExponent Reals RealSign Reap RecognitionPrior RecognitionThreshold Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RectangularRepeatingElement RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate Region RegionBinarize RegionBoundary RegionBounds RegionCentroid RegionDifference RegionDimension RegionDisjoint RegionDistance RegionDistanceFunction RegionEmbeddingDimension RegionEqual RegionFunction RegionImage RegionIntersection RegionMeasure RegionMember RegionMemberFunction RegionMoment RegionNearest RegionNearestFunction RegionPlot RegionPlot3D RegionProduct RegionQ RegionResize RegionSize RegionSymmetricDifference RegionUnion RegionWithin RegisterExternalEvaluator RegularExpression Regularization RegularlySampledQ RegularPolygon ReIm ReImLabels ReImPlot ReImStyle Reinstall RelationalDatabase RelationGraph Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot RemoteAuthorizationCaching RemoteConnect RemoteConnectionObject RemoteFile RemoteRun RemoteRunProcess Remove RemoveAlphaChannel RemoveAsynchronousTask RemoveAudioStream RemoveBackground RemoveChannelListener RemoveChannelSubscribers Removed RemoveDiacritics RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RemoveUsers RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart RepairMesh Repeated RepeatedNull RepeatedString RepeatedTiming RepeatingElement Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated ReplicateLayer RequiredPhysicalQuantities Resampling ResamplingAlgorithmData ResamplingMethod Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask ReshapeLayer Residue ResizeLayer Resolve ResourceAcquire ResourceData ResourceFunction ResourceObject ResourceRegister ResourceRemove ResourceSearch ResourceSubmissionObject ResourceSubmit ResourceSystemBase ResourceUpdate ResponseForm Rest RestartInterval Restricted Resultant ResumePacket Return ReturnEntersInput ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnReceiptFunction ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseSort ReverseSortBy ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ RiemannXi Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightComposition RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity RollPitchYawAngles RollPitchYawMatrix RomanNumeral Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RSolveValue RudinShapiro RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulePlot RulerUnits Run RunProcess RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilaritySameQ SameTest SampledEntityClass SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SASTriangle SatelliteData SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveConnection SaveDefinitions SavitzkyGolayMatrix SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTask ScheduledTaskActiveQ ScheduledTaskInformation ScheduledTaskInformationData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScientificNotationThreshold ScorerGi ScorerGiPrime ScorerHi ScorerHiPrime ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptForm ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition SearchAdjustment SearchIndexObject SearchIndices SearchQueryString SearchResultObject Sec Sech SechDistribution SecondOrderConeOptimization SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SecuredAuthenticationKey SecuredAuthenticationKeys SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook SelectFirst Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemanticImport SemanticImportString SemanticInterpretation SemialgebraicComponentInstances SemidefiniteOptimization SendMail SendMessage Sequence SequenceAlignment SequenceAttentionLayer SequenceCases SequenceCount SequenceFold SequenceFoldList SequenceForm SequenceHold SequenceLastLayer SequenceMostLayer SequencePosition SequencePredict SequencePredictorFunction SequenceReplace SequenceRestLayer SequenceReverseLayer SequenceSplit Series SeriesCoefficient SeriesData ServiceConnect ServiceDisconnect ServiceExecute ServiceObject ServiceRequest ServiceResponse ServiceSubmit SessionSubmit SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetCloudDirectory SetCookies SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPermissions SetPrecision SetProperty SetSecuredAuthenticationKey SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemModel SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetUsers SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share SharingList Sharpen ShearingMatrix ShearingTransform ShellRegion ShenCastanMatrix ShiftedGompertzDistribution ShiftRegisterSequence Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortTimeFourier ShortTimeFourierData ShortUpArrow Show ShowAutoConvert ShowAutoSpellCheck ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowCodeAssist ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiderealTime SiegelTheta SiegelTukeyTest SierpinskiCurve SierpinskiMesh Sign Signature SignedRankTest SignedRegionDistance SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ SimplePolygonQ SimplePolyhedronQ Simplex Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution SkinStyle Skip SliceContourPlot3D SliceDensityPlot3D SliceDistribution SliceVectorPlot3D Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDecomposition SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SnDispersion Snippet SnubPolyhedron SocialMediaData Socket SocketConnect SocketListen SocketListener SocketObject SocketOpen SocketReadMessage SocketReadyQ Sockets SocketWaitAll SocketWaitNext SoftmaxLayer SokalSneathDissimilarity SolarEclipse SolarSystemFeatureData SolidAngle SolidData SolidRegionQ Solve SolveAlways SolveDelayed Sort SortBy SortedBy SortedEntityClass Sound SoundAndGraphics SoundNote SoundVolume SourceLink Sow Space SpaceCurveData SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution SpatialMedian SpatialTransformationLayer Speak SpeakTextPacket SpearmanRankTest SpearmanRho SpeciesData SpecificityGoal SpectralLineData Spectrogram SpectrogramArray Specularity SpeechRecognize SpeechSynthesize SpellingCorrection SpellingCorrectionList SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SpherePoints SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SphericalShell SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquareMatrixQ SquareRepeatingElement SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave SSSTriangle StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackedDateListPlot StackedListPlot StackInhibit StadiumShape StandardAtmosphereData StandardDeviation StandardDeviationFilter StandardForm Standardize Standardized StandardOceanData StandbyDistribution Star StarClusterData StarData StarGraph StartAsynchronousTask StartExternalSession StartingStepSize StartOfLine StartOfString StartProcess StartScheduledTask StartupSound StartWebSession StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StateTransformationLinearize StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StereochemistryElements StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StoppingPowerData StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamMarkers StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringContainsQ StringCount StringDelete StringDrop StringEndsQ StringExpression StringExtract StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPadLeft StringPadRight StringPart StringPartition StringPosition StringQ StringRepeat StringReplace StringReplaceList StringReplacePart StringReverse StringRiffle StringRotateLeft StringRotateRight StringSkeleton StringSplit StringStartsQ StringTake StringTemplate StringToByteArray StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleData StyleDefinitions StyleForm StyleHints StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subdivide Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subsequences Subset SubsetEqual SubsetMap SubsetQ Subsets SubStar SubstitutionSystem Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubtractSides SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde Success SuchThat Sum SumConvergence SummationLayer Sunday SunPosition Sunrise Sunset SuperDagger SuperMinus SupernovaData SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceArea SurfaceColor SurfaceData SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricKey SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Synonyms Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SynthesizeMissingValues SystemDialogInput SystemException SystemGet SystemHelpPath SystemInformation SystemInformationData SystemInstall SystemModel SystemModeler SystemModelExamples SystemModelLinearize SystemModelParametricSimulate SystemModelPlot SystemModelProgressReporting SystemModelReliability SystemModels SystemModelSimulate SystemModelSimulateSensitivity SystemModelSimulationData SystemOpen SystemOptions SystemProcessData SystemProcesses SystemsConnectionsModel SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelLinearity SystemsModelMerge SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemsModelVectorRelativeOrders SystemStub SystemTestTab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TableViewBoxBackground TableViewBoxOptions TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeDrop TakeLargest TakeLargestBy TakeList TakeSmallest TakeSmallestBy TakeWhile Tally Tan Tanh TargetDevice TargetFunctions TargetSystem TargetUnits TaskAbort TaskExecute TaskObject TaskRemove TaskResume Tasks TaskSuspend TaskWait TautologyQ TelegraphProcess TemplateApply TemplateArgBox TemplateBox TemplateBoxOptions TemplateEvaluate TemplateExpression TemplateIf TemplateObject TemplateSequence TemplateSlot TemplateSlotSequence TemplateUnevaluated TemplateVerbatim TemplateWith TemporalData TemporalRegularity Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge TestID TestReport TestReportObject TestResultObject Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCases TextCell TextClipboardType TextContents TextData TextElement TextForm TextGrid TextJustification TextLine TextPacket TextParagraph TextPosition TextRecognize TextSearch TextSearchReport TextSentences TextString TextStructure TextStyle TextTranslation Texture TextureCoordinateFunction TextureCoordinateScaling TextWords Therefore ThermodynamicData ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreadingLayer ThreeJSymbol Threshold Through Throw ThueMorse Thumbnail Thursday Ticks TicksStyle TideData Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint TimeDirection TimeFormat TimeGoal TimelinePlot TimeObject TimeObjectQ Times TimesBy TimeSeries TimeSeriesAggregate TimeSeriesForecast TimeSeriesInsert TimeSeriesInvertibility TimeSeriesMap TimeSeriesMapThread TimeSeriesModel TimeSeriesModelFit TimeSeriesResample TimeSeriesRescale TimeSeriesShift TimeSeriesThread TimeSeriesWindow TimeUsed TimeValue TimeWarpingCorrespondence TimeWarpingDistance TimeZone TimeZoneConvert TimeZoneOffset Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate Today ToDiscreteTimeModel ToEntity ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase Tomorrow ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform ToPolarCoordinates TopologicalSort ToRadicals ToRules ToSphericalCoordinates ToString Total TotalHeight TotalLayer TotalVariationFilter TotalWidth TouchPosition TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TrackingFunction TracyWidomDistribution TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TrainingProgressCheckpointing TrainingProgressFunction TrainingProgressMeasurements TrainingProgressReporting TrainingStoppingCriterion TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationClass TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField TransformedProcess TransformedRegion TransitionDirection TransitionDuration TransitionEffect TransitiveClosureGraph TransitiveReductionGraph Translate TranslationOptions TranslationTransform Transliterate Transparent TransparentColor Transpose TransposeLayer TrapSelection TravelDirections TravelDirectionsData TravelDistance TravelDistanceList TravelMethod TravelTime TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle Triangle TriangleCenter TriangleConstruct TriangleMeasurement TriangleWave TriangularDistribution TriangulateMesh Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean TrimmedVariance TropicalStormData True TrueQ TruncatedDistribution TruncatedPolyhedron TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBoxOptions TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow TunnelData Tuples TuranGraph TuringMachine TuttePolynomial TwoWayRule Typed TypeSpecifierUnateQ Uncompress UnconstrainedParameters Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UnderseaFeatureData UndirectedEdge UndirectedGraph UndirectedGraphQ UndoOptions UndoTrackedVariables Unequal UnequalTo Unevaluated UniformDistribution UniformGraphDistribution UniformPolyhedron UniformSumDistribution Uninstall Union UnionPlus Unique UnitaryMatrixQ UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitSystem UnitTriangle UnitVector UnitVectorLayer UnityDimensions UniverseModelData UniversityData UnixTime Unprotect UnregisterExternalEvaluator UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpdateSearchIndex UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize UpperTriangularMatrixQ Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpTo UpValues URL URLBuild URLDecode URLDispatcher URLDownload URLDownloadSubmit URLEncode URLExecute URLExpand URLFetch URLFetchAsynchronous URLParse URLQueryDecode URLQueryEncode URLRead URLResponseTime URLSave URLSaveAsynchronous URLShorten URLSubmit UseGraphicsRange UserDefinedWavelet Using UsingFrontEnd UtilityFunctionV2Get ValenceErrorHandling ValidationLength ValidationSet Value ValueBox ValueBoxOptions ValueDimensions ValueForm ValuePreprocessingFunction ValueQ Values ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorAround VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorGreater VectorGreaterEqual VectorLess VectorLessEqual VectorMarkers VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerificationTest VerifyConvergence VerifyDerivedKey VerifyDigitalSignature VerifyInterpretation VerifySecurityCertificates VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexContract VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight VertexWeightedGraphQ Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewProjection ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoiceStyleData VoigtDistribution VolcanoData Volume VonMisesDistribution VoronoiMeshWaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WarpingCorrespondence WarpingDistance WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeatherForecastData WebAudioSearch WebElementObject WeberE WebExecute WebImage WebImageSearch WebSearch WebSessionObject WebSessions WebWindowObject Wedge Wednesday WeibullDistribution WeierstrassE1 WeierstrassE2 WeierstrassE3 WeierstrassEta1 WeierstrassEta2 WeierstrassEta3 WeierstrassHalfPeriods WeierstrassHalfPeriodW1 WeierstrassHalfPeriodW2 WeierstrassHalfPeriodW3 WeierstrassInvariantG2 WeierstrassInvariantG3 WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White WhiteNoiseProcess WhitePoint Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WikipediaData WikipediaSearch WilksW WilksWTest WindDirectionData WindingCount WindingPolygon WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowPersistentStyles WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth WindSpeedData WindVectorData WinsorizedMean WinsorizedVariance WishartMatrixDistribution With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult WolframLanguageData Word WordBoundary WordCharacter WordCloud WordCount WordCounts WordData WordDefinition WordFrequency WordFrequencyData WordList WordOrientation WordSearch WordSelectionFunction WordSeparators WordSpacings WordStem WordTranslation WorkingPrecision WrapAround Write WriteLine WriteString WronskianXMLElement XMLObject XMLTemplate Xnor Xor XYZColorYellow Yesterday YuleDissimilarityZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZIPCodeData ZipfDistribution ZoomCenter ZoomFactor ZTest ZTransform$Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AllowExternalChannelFunctions $AssertFunction $Assumptions $AsynchronousTask $AudioInputDevices $AudioOutputDevices $BaseDirectory $BatchInput $BatchOutput $BlockchainBase $BoxForms $ByteOrdering $CacheBaseDirectory $Canceled $ChannelBase $CharacterEncoding $CharacterEncodings $CloudBase $CloudConnected $CloudCreditsAvailable $CloudEvaluation $CloudExpressionBase $CloudObjectNameFormat $CloudObjectURLType $CloudRootDirectory $CloudSymbolBase $CloudUserID $CloudUserUUID $CloudVersion $CloudVersionNumber $CloudWolframEngineVersionNumber $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $Cookies $CookieStore $CreationDate $CurrentLink $CurrentTask $CurrentWebSession $DateStringFormat $DefaultAudioInputDevice $DefaultAudioOutputDevice $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultLocalBase $DefaultMailbox $DefaultNetworkInterface $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $EmbedCodeEnvironments $EmbeddableServices $EntityStores $Epilog $EvaluationCloudBase $EvaluationCloudObject $EvaluationEnvironment $ExportFormats $Failed $FinancialDataSource $FontFamilies $FormatType $FrontEnd $FrontEndSession $GeoEntityTypes $GeoLocation $GeoLocationCity $GeoLocationCountry $GeoLocationPrecision $GeoLocationSource $HistoryLength $HomeDirectory $HTMLExportRules $HTTPCookies $HTTPRequest $IgnoreEOF $ImageFormattingWidth $ImagingDevice $ImagingDevices $ImportFormats $IncomingMailSettings $InitialDirectory $Initialization $InitializationContexts $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $InterpreterTypes $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $LocalBase $LocalSymbolBase $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $MobilePhone $ModuleNumber $NetworkConnected $NetworkInterfaces $NetworkLicense $NewMessage $NewSymbol $Notebooks $NoValue $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $Permissions $PermissionsGroupBase $PersistenceBase $PersistencePath $PipeSupported $PlotTheme $Post $Pre $PreferencesDirectory $PreInitialization $PrePrint $PreRead $PrintForms $PrintLiteral $Printout3DPreviewer $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $PublisherID $RandomState $RecursionLimit $RegisteredDeviceClasses $RegisteredUserName $ReleaseNumber $RequesterAddress $RequesterWolframID $RequesterWolframUUID $ResourceSystemBase $RootDirectory $ScheduledTask $ScriptCommandLine $ScriptInputString $SecuredAuthenticationKeyTokens $ServiceCreditsAvailable $Services $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SourceLink $SSHAuthentication $SummaryBoxDataSizeLimit $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemMemory $SystemShell $SystemTimeZone $SystemWordLength $TemplatePath $TemporaryDirectory $TemporaryPrefix $TestFileName $TextStyle $TimedOut $TimeUnit $TimeZone $TimeZoneEntity $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $UnitSystem $Urgent $UserAddOnsDirectory $UserAgentLanguages $UserAgentMachine $UserAgentName $UserAgentOperatingSystem $UserAgentString $UserAgentVersion $UserBaseDirectory $UserDocumentsDirectory $Username $UserName $UserURLBase $Version $VersionNumber $VoiceStyles $WolframID $WolframUUID",
 contains:[a.COMMENT("\\(\\*","\\*\\)",{contains:["self"]}),a.QUOTE_STRING_MODE,a.C_NUMBER_MODE]}});b.registerLanguage("matlab",function(a){var b={relevance:0,contains:[{begin:"('|\\.')+"}]};return{keywords:{keyword:"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while",built_in:"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson max min nanmax nanmin mean nanmean type table readtable writetable sortrows sort figure plot plot3 scatter scatter3 cellfun legend intersect ismember procrustes hold num2cell "},
 illegal:'(//|"|#|/\\*|\\s+/\\w+)',contains:[{className:"function",beginKeywords:"function",end:"$",contains:[a.UNDERSCORE_TITLE_MODE,{className:"params",variants:[{begin:"\\(",end:"\\)"},{begin:"\\[",end:"\\]"}]}]},{className:"built_in",begin:/true|false/,relevance:0,starts:b},{begin:"[a-zA-Z][a-zA-Z_0-9]*('|\\.')+",relevance:0},{className:"number",begin:a.C_NUMBER_RE,relevance:0,starts:b},{className:"string",begin:"'",end:"'",contains:[a.BACKSLASH_ESCAPE,{begin:"''"}]},{begin:/\]|}|\)/,relevance:0,
 starts:b},{className:"string",begin:'"',end:'"',contains:[a.BACKSLASH_ESCAPE,{begin:'""'}],starts:b},a.COMMENT("^\\s*\\%\\{\\s*$","^\\s*\\%\\}\\s*$"),a.COMMENT("\\%","$")]}});b.registerLanguage("maxima",function(a){return{lexemes:"[A-Za-z_%][0-9A-Za-z_%]*",keywords:{keyword:"if then else elseif for thru do while unless step in and or not",literal:"true false unknown inf minf ind und %e %i %pi %phi %gamma",built_in:" abasep abs absint absolute_real_time acos acosh acot acoth acsc acsch activate addcol add_edge add_edges addmatrices addrow add_vertex add_vertices adjacency_matrix adjoin adjoint af agd airy airy_ai airy_bi airy_dai airy_dbi algsys alg_type alias allroots alphacharp alphanumericp amortization %and annuity_fv annuity_pv antid antidiff AntiDifference append appendfile apply apply1 apply2 applyb1 apropos args arit_amortization arithmetic arithsum array arrayapply arrayinfo arraymake arraysetapply ascii asec asech asin asinh askinteger asksign assoc assoc_legendre_p assoc_legendre_q assume assume_external_byte_order asympa at atan atan2 atanh atensimp atom atvalue augcoefmatrix augmented_lagrangian_method av average_degree backtrace bars barsplot barsplot_description base64 base64_decode bashindices batch batchload bc2 bdvac belln benefit_cost bern bernpoly bernstein_approx bernstein_expand bernstein_poly bessel bessel_i bessel_j bessel_k bessel_simplify bessel_y beta beta_incomplete beta_incomplete_generalized beta_incomplete_regularized bezout bfallroots bffac bf_find_root bf_fmin_cobyla bfhzeta bfloat bfloatp bfpsi bfpsi0 bfzeta biconnected_components bimetric binomial bipartition block blockmatrixp bode_gain bode_phase bothcoef box boxplot boxplot_description break bug_report build_info|10 buildq build_sample burn cabs canform canten cardinality carg cartan cartesian_product catch cauchy_matrix cbffac cdf_bernoulli cdf_beta cdf_binomial cdf_cauchy cdf_chi2 cdf_continuous_uniform cdf_discrete_uniform cdf_exp cdf_f cdf_gamma cdf_general_finite_discrete cdf_geometric cdf_gumbel cdf_hypergeometric cdf_laplace cdf_logistic cdf_lognormal cdf_negative_binomial cdf_noncentral_chi2 cdf_noncentral_student_t cdf_normal cdf_pareto cdf_poisson cdf_rank_sum cdf_rayleigh cdf_signed_rank cdf_student_t cdf_weibull cdisplay ceiling central_moment cequal cequalignore cf cfdisrep cfexpand cgeodesic cgreaterp cgreaterpignore changename changevar chaosgame charat charfun charfun2 charlist charp charpoly chdir chebyshev_t chebyshev_u checkdiv check_overlaps chinese cholesky christof chromatic_index chromatic_number cint circulant_graph clear_edge_weight clear_rules clear_vertex_label clebsch_gordan clebsch_graph clessp clesspignore close closefile cmetric coeff coefmatrix cograd col collapse collectterms columnop columnspace columnswap columnvector combination combine comp2pui compare compfile compile compile_file complement_graph complete_bipartite_graph complete_graph complex_number_p components compose_functions concan concat conjugate conmetderiv connected_components connect_vertices cons constant constantp constituent constvalue cont2part content continuous_freq contortion contour_plot contract contract_edge contragrad contrib_ode convert coord copy copy_file copy_graph copylist copymatrix cor cos cosh cot coth cov cov1 covdiff covect covers crc24sum create_graph create_list csc csch csetup cspline ctaylor ct_coordsys ctransform ctranspose cube_graph cuboctahedron_graph cunlisp cv cycle_digraph cycle_graph cylindrical days360 dblint deactivate declare declare_constvalue declare_dimensions declare_fundamental_dimensions declare_fundamental_units declare_qty declare_translated declare_unit_conversion declare_units declare_weights decsym defcon define define_alt_display define_variable defint defmatch defrule defstruct deftaylor degree_sequence del delete deleten delta demo demoivre denom depends derivdegree derivlist describe desolve determinant dfloat dgauss_a dgauss_b dgeev dgemm dgeqrf dgesv dgesvd diag diagmatrix diag_matrix diagmatrixp diameter diff digitcharp dimacs_export dimacs_import dimension dimensionless dimensions dimensions_as_list direct directory discrete_freq disjoin disjointp disolate disp dispcon dispform dispfun dispJordan display disprule dispterms distrib divide divisors divsum dkummer_m dkummer_u dlange dodecahedron_graph dotproduct dotsimp dpart draw draw2d draw3d drawdf draw_file draw_graph dscalar echelon edge_coloring edge_connectivity edges eigens_by_jacobi eigenvalues eigenvectors eighth einstein eivals eivects elapsed_real_time elapsed_run_time ele2comp ele2polynome ele2pui elem elementp elevation_grid elim elim_allbut eliminate eliminate_using ellipse elliptic_e elliptic_ec elliptic_eu elliptic_f elliptic_kc elliptic_pi ematrix empty_graph emptyp endcons entermatrix entertensor entier equal equalp equiv_classes erf erfc erf_generalized erfi errcatch error errormsg errors euler ev eval_string evenp every evolution evolution2d evundiff example exp expand expandwrt expandwrt_factored expint expintegral_chi expintegral_ci expintegral_e expintegral_e1 expintegral_ei expintegral_e_simplify expintegral_li expintegral_shi expintegral_si explicit explose exponentialize express expt exsec extdiff extract_linear_equations extremal_subset ezgcd %f f90 facsum factcomb factor factorfacsum factorial factorout factorsum facts fast_central_elements fast_linsolve fasttimes featurep fernfale fft fib fibtophi fifth filename_merge file_search file_type fillarray findde find_root find_root_abs find_root_error find_root_rel first fix flatten flength float floatnump floor flower_snark flush flush1deriv flushd flushnd flush_output fmin_cobyla forget fortran fourcos fourexpand fourier fourier_elim fourint fourintcos fourintsin foursimp foursin fourth fposition frame_bracket freeof freshline fresnel_c fresnel_s from_adjacency_matrix frucht_graph full_listify fullmap fullmapl fullratsimp fullratsubst fullsetify funcsolve fundamental_dimensions fundamental_units fundef funmake funp fv g0 g1 gamma gamma_greek gamma_incomplete gamma_incomplete_generalized gamma_incomplete_regularized gauss gauss_a gauss_b gaussprob gcd gcdex gcdivide gcfac gcfactor gd generalized_lambert_w genfact gen_laguerre genmatrix gensym geo_amortization geo_annuity_fv geo_annuity_pv geomap geometric geometric_mean geosum get getcurrentdirectory get_edge_weight getenv get_lu_factors get_output_stream_string get_pixel get_plot_option get_tex_environment get_tex_environment_default get_vertex_label gfactor gfactorsum ggf girth global_variances gn gnuplot_close gnuplot_replot gnuplot_reset gnuplot_restart gnuplot_start go Gosper GosperSum gr2d gr3d gradef gramschmidt graph6_decode graph6_encode graph6_export graph6_import graph_center graph_charpoly graph_eigenvalues graph_flow graph_order graph_periphery graph_product graph_size graph_union great_rhombicosidodecahedron_graph great_rhombicuboctahedron_graph grid_graph grind grobner_basis grotzch_graph hamilton_cycle hamilton_path hankel hankel_1 hankel_2 harmonic harmonic_mean hav heawood_graph hermite hessian hgfred hilbertmap hilbert_matrix hipow histogram histogram_description hodge horner hypergeometric i0 i1 %ibes ic1 ic2 ic_convert ichr1 ichr2 icosahedron_graph icosidodecahedron_graph icurvature ident identfor identity idiff idim idummy ieqn %if ifactors iframes ifs igcdex igeodesic_coords ilt image imagpart imetric implicit implicit_derivative implicit_plot indexed_tensor indices induced_subgraph inferencep inference_result infix info_display init_atensor init_ctensor in_neighbors innerproduct inpart inprod inrt integerp integer_partitions integrate intersect intersection intervalp intopois intosum invariant1 invariant2 inverse_fft inverse_jacobi_cd inverse_jacobi_cn inverse_jacobi_cs inverse_jacobi_dc inverse_jacobi_dn inverse_jacobi_ds inverse_jacobi_nc inverse_jacobi_nd inverse_jacobi_ns inverse_jacobi_sc inverse_jacobi_sd inverse_jacobi_sn invert invert_by_adjoint invert_by_lu inv_mod irr is is_biconnected is_bipartite is_connected is_digraph is_edge_in_graph is_graph is_graph_or_digraph ishow is_isomorphic isolate isomorphism is_planar isqrt isreal_p is_sconnected is_tree is_vertex_in_graph items_inference %j j0 j1 jacobi jacobian jacobi_cd jacobi_cn jacobi_cs jacobi_dc jacobi_dn jacobi_ds jacobi_nc jacobi_nd jacobi_ns jacobi_p jacobi_sc jacobi_sd jacobi_sn JF jn join jordan julia julia_set julia_sin %k kdels kdelta kill killcontext kostka kron_delta kronecker_product kummer_m kummer_u kurtosis kurtosis_bernoulli kurtosis_beta kurtosis_binomial kurtosis_chi2 kurtosis_continuous_uniform kurtosis_discrete_uniform kurtosis_exp kurtosis_f kurtosis_gamma kurtosis_general_finite_discrete kurtosis_geometric kurtosis_gumbel kurtosis_hypergeometric kurtosis_laplace kurtosis_logistic kurtosis_lognormal kurtosis_negative_binomial kurtosis_noncentral_chi2 kurtosis_noncentral_student_t kurtosis_normal kurtosis_pareto kurtosis_poisson kurtosis_rayleigh kurtosis_student_t kurtosis_weibull label labels lagrange laguerre lambda lambert_w laplace laplacian_matrix last lbfgs lc2kdt lcharp lc_l lcm lc_u ldefint ldisp ldisplay legendre_p legendre_q leinstein length let letrules letsimp levi_civita lfreeof lgtreillis lhs li liediff limit Lindstedt linear linearinterpol linear_program linear_regression line_graph linsolve listarray list_correlations listify list_matrix_entries list_nc_monomials listoftens listofvars listp lmax lmin load loadfile local locate_matrix_entry log logcontract log_gamma lopow lorentz_gauge lowercasep lpart lratsubst lreduce lriemann lsquares_estimates lsquares_estimates_approximate lsquares_estimates_exact lsquares_mse lsquares_residual_mse lsquares_residuals lsum ltreillis lu_backsub lucas lu_factor %m macroexpand macroexpand1 make_array makebox makefact makegamma make_graph make_level_picture makelist makeOrders make_poly_continent make_poly_country make_polygon make_random_state make_rgb_picture makeset make_string_input_stream make_string_output_stream make_transform mandelbrot mandelbrot_set map mapatom maplist matchdeclare matchfix mat_cond mat_fullunblocker mat_function mathml_display mat_norm matrix matrixmap matrixp matrix_size mattrace mat_trace mat_unblocker max max_clique max_degree max_flow maximize_lp max_independent_set max_matching maybe md5sum mean mean_bernoulli mean_beta mean_binomial mean_chi2 mean_continuous_uniform mean_deviation mean_discrete_uniform mean_exp mean_f mean_gamma mean_general_finite_discrete mean_geometric mean_gumbel mean_hypergeometric mean_laplace mean_logistic mean_lognormal mean_negative_binomial mean_noncentral_chi2 mean_noncentral_student_t mean_normal mean_pareto mean_poisson mean_rayleigh mean_student_t mean_weibull median median_deviation member mesh metricexpandall mgf1_sha1 min min_degree min_edge_cut minfactorial minimalPoly minimize_lp minimum_spanning_tree minor minpack_lsquares minpack_solve min_vertex_cover min_vertex_cut mkdir mnewton mod mode_declare mode_identity ModeMatrix moebius mon2schur mono monomial_dimensions multibernstein_poly multi_display_for_texinfo multi_elem multinomial multinomial_coeff multi_orbit multiplot_mode multi_pui multsym multthru mycielski_graph nary natural_unit nc_degree ncexpt ncharpoly negative_picture neighbors new newcontext newdet new_graph newline newton new_variable next_prime nicedummies niceindices ninth nofix nonarray noncentral_moment nonmetricity nonnegintegerp nonscalarp nonzeroandfreeof notequal nounify nptetrad npv nroots nterms ntermst nthroot nullity nullspace num numbered_boundaries numberp number_to_octets num_distinct_partitions numerval numfactor num_partitions nusum nzeta nzetai nzetar octets_to_number octets_to_oid odd_girth oddp ode2 ode_check odelin oid_to_octets op opena opena_binary openr openr_binary openw openw_binary operatorp opsubst optimize %or orbit orbits ordergreat ordergreatp orderless orderlessp orthogonal_complement orthopoly_recur orthopoly_weight outermap out_neighbors outofpois pade parabolic_cylinder_d parametric parametric_surface parg parGosper parse_string parse_timedate part part2cont partfrac partition partition_set partpol path_digraph path_graph pathname_directory pathname_name pathname_type pdf_bernoulli pdf_beta pdf_binomial pdf_cauchy pdf_chi2 pdf_continuous_uniform pdf_discrete_uniform pdf_exp pdf_f pdf_gamma pdf_general_finite_discrete pdf_geometric pdf_gumbel pdf_hypergeometric pdf_laplace pdf_logistic pdf_lognormal pdf_negative_binomial pdf_noncentral_chi2 pdf_noncentral_student_t pdf_normal pdf_pareto pdf_poisson pdf_rank_sum pdf_rayleigh pdf_signed_rank pdf_student_t pdf_weibull pearson_skewness permanent permut permutation permutations petersen_graph petrov pickapart picture_equalp picturep piechart piechart_description planar_embedding playback plog plot2d plot3d plotdf ploteq plsquares pochhammer points poisdiff poisexpt poisint poismap poisplus poissimp poissubst poistimes poistrim polar polarform polartorect polar_to_xy poly_add poly_buchberger poly_buchberger_criterion poly_colon_ideal poly_content polydecomp poly_depends_p poly_elimination_ideal poly_exact_divide poly_expand poly_expt poly_gcd polygon poly_grobner poly_grobner_equal poly_grobner_member poly_grobner_subsetp poly_ideal_intersection poly_ideal_polysaturation poly_ideal_polysaturation1 poly_ideal_saturation poly_ideal_saturation1 poly_lcm poly_minimization polymod poly_multiply polynome2ele polynomialp poly_normal_form poly_normalize poly_normalize_list poly_polysaturation_extension poly_primitive_part poly_pseudo_divide poly_reduced_grobner poly_reduction poly_saturation_extension poly_s_polynomial poly_subtract polytocompanion pop postfix potential power_mod powerseries powerset prefix prev_prime primep primes principal_components print printf printfile print_graph printpois printprops prodrac product properties propvars psi psubst ptriangularize pui pui2comp pui2ele pui2polynome pui_direct puireduc push put pv qput qrange qty quad_control quad_qag quad_qagi quad_qagp quad_qags quad_qawc quad_qawf quad_qawo quad_qaws quadrilateral quantile quantile_bernoulli quantile_beta quantile_binomial quantile_cauchy quantile_chi2 quantile_continuous_uniform quantile_discrete_uniform quantile_exp quantile_f quantile_gamma quantile_general_finite_discrete quantile_geometric quantile_gumbel quantile_hypergeometric quantile_laplace quantile_logistic quantile_lognormal quantile_negative_binomial quantile_noncentral_chi2 quantile_noncentral_student_t quantile_normal quantile_pareto quantile_poisson quantile_rayleigh quantile_student_t quantile_weibull quartile_skewness quit qunit quotient racah_v racah_w radcan radius random random_bernoulli random_beta random_binomial random_bipartite_graph random_cauchy random_chi2 random_continuous_uniform random_digraph random_discrete_uniform random_exp random_f random_gamma random_general_finite_discrete random_geometric random_graph random_graph1 random_gumbel random_hypergeometric random_laplace random_logistic random_lognormal random_negative_binomial random_network random_noncentral_chi2 random_noncentral_student_t random_normal random_pareto random_permutation random_poisson random_rayleigh random_regular_graph random_student_t random_tournament random_tree random_weibull range rank rat ratcoef ratdenom ratdiff ratdisrep ratexpand ratinterpol rational rationalize ratnumer ratnump ratp ratsimp ratsubst ratvars ratweight read read_array read_binary_array read_binary_list read_binary_matrix readbyte readchar read_hashed_array readline read_list read_matrix read_nested_list readonly read_xpm real_imagpart_to_conjugate realpart realroots rearray rectangle rectform rectform_log_if_constant recttopolar rediff reduce_consts reduce_order region region_boundaries region_boundaries_plus rem remainder remarray rembox remcomps remcon remcoord remfun remfunction remlet remove remove_constvalue remove_dimensions remove_edge remove_fundamental_dimensions remove_fundamental_units remove_plot_option remove_vertex rempart remrule remsym remvalue rename rename_file reset reset_displays residue resolvante resolvante_alternee1 resolvante_bipartite resolvante_diedrale resolvante_klein resolvante_klein3 resolvante_produit_sym resolvante_unitaire resolvante_vierer rest resultant return reveal reverse revert revert2 rgb2level rhs ricci riemann rinvariant risch rk rmdir rncombine romberg room rootscontract round row rowop rowswap rreduce run_testsuite %s save saving scalarp scaled_bessel_i scaled_bessel_i0 scaled_bessel_i1 scalefactors scanmap scatterplot scatterplot_description scene schur2comp sconcat scopy scsimp scurvature sdowncase sec sech second sequal sequalignore set_alt_display setdifference set_draw_defaults set_edge_weight setelmx setequalp setify setp set_partitions set_plot_option set_prompt set_random_state set_tex_environment set_tex_environment_default setunits setup_autoload set_up_dot_simplifications set_vertex_label seventh sexplode sf sha1sum sha256sum shortest_path shortest_weighted_path show showcomps showratvars sierpinskiale sierpinskimap sign signum similaritytransform simp_inequality simplify_sum simplode simpmetderiv simtran sin sinh sinsert sinvertcase sixth skewness skewness_bernoulli skewness_beta skewness_binomial skewness_chi2 skewness_continuous_uniform skewness_discrete_uniform skewness_exp skewness_f skewness_gamma skewness_general_finite_discrete skewness_geometric skewness_gumbel skewness_hypergeometric skewness_laplace skewness_logistic skewness_lognormal skewness_negative_binomial skewness_noncentral_chi2 skewness_noncentral_student_t skewness_normal skewness_pareto skewness_poisson skewness_rayleigh skewness_student_t skewness_weibull slength smake small_rhombicosidodecahedron_graph small_rhombicuboctahedron_graph smax smin smismatch snowmap snub_cube_graph snub_dodecahedron_graph solve solve_rec solve_rec_rat some somrac sort sparse6_decode sparse6_encode sparse6_export sparse6_import specint spherical spherical_bessel_j spherical_bessel_y spherical_hankel1 spherical_hankel2 spherical_harmonic spherical_to_xyz splice split sposition sprint sqfr sqrt sqrtdenest sremove sremovefirst sreverse ssearch ssort sstatus ssubst ssubstfirst staircase standardize standardize_inverse_trig starplot starplot_description status std std1 std_bernoulli std_beta std_binomial std_chi2 std_continuous_uniform std_discrete_uniform std_exp std_f std_gamma std_general_finite_discrete std_geometric std_gumbel std_hypergeometric std_laplace std_logistic std_lognormal std_negative_binomial std_noncentral_chi2 std_noncentral_student_t std_normal std_pareto std_poisson std_rayleigh std_student_t std_weibull stemplot stirling stirling1 stirling2 strim striml strimr string stringout stringp strong_components struve_h struve_l sublis sublist sublist_indices submatrix subsample subset subsetp subst substinpart subst_parallel substpart substring subvar subvarp sum sumcontract summand_to_rec supcase supcontext symbolp symmdifference symmetricp system take_channel take_inference tan tanh taylor taylorinfo taylorp taylor_simplifier taytorat tcl_output tcontract tellrat tellsimp tellsimpafter tentex tenth test_mean test_means_difference test_normality test_proportion test_proportions_difference test_rank_sum test_sign test_signed_rank test_variance test_variance_ratio tex tex1 tex_display texput %th third throw time timedate timer timer_info tldefint tlimit todd_coxeter toeplitz tokens to_lisp topological_sort to_poly to_poly_solve totaldisrep totalfourier totient tpartpol trace tracematrix trace_options transform_sample translate translate_file transpose treefale tree_reduce treillis treinat triangle triangularize trigexpand trigrat trigreduce trigsimp trunc truncate truncated_cube_graph truncated_dodecahedron_graph truncated_icosahedron_graph truncated_tetrahedron_graph tr_warnings_get tube tutte_graph ueivects uforget ultraspherical underlying_graph undiff union unique uniteigenvectors unitp units unit_step unitvector unorder unsum untellrat untimer untrace uppercasep uricci uriemann uvect vandermonde_matrix var var1 var_bernoulli var_beta var_binomial var_chi2 var_continuous_uniform var_discrete_uniform var_exp var_f var_gamma var_general_finite_discrete var_geometric var_gumbel var_hypergeometric var_laplace var_logistic var_lognormal var_negative_binomial var_noncentral_chi2 var_noncentral_student_t var_normal var_pareto var_poisson var_rayleigh var_student_t var_weibull vector vectorpotential vectorsimp verbify vers vertex_coloring vertex_connectivity vertex_degree vertex_distance vertex_eccentricity vertex_in_degree vertex_out_degree vertices vertices_to_cycle vertices_to_path %w weyl wheel_graph wiener_index wigner_3j wigner_6j wigner_9j with_stdout write_binary_data writebyte write_data writefile wronskian xreduce xthru %y Zeilberger zeroequiv zerofor zeromatrix zeromatrixp zeta zgeev zheev zlange zn_add_table zn_carmichael_lambda zn_characteristic_factors zn_determinant zn_factor_generators zn_invert_by_lu zn_log zn_mult_table absboxchar activecontexts adapt_depth additive adim aform algebraic algepsilon algexact aliases allbut all_dotsimp_denoms allocation allsym alphabetic animation antisymmetric arrays askexp assume_pos assume_pos_pred assumescalar asymbol atomgrad atrig1 axes axis_3d axis_bottom axis_left axis_right axis_top azimuth background background_color backsubst berlefact bernstein_explicit besselexpand beta_args_sum_to_integer beta_expand bftorat bftrunc bindtest border boundaries_array box boxchar breakup %c capping cauchysum cbrange cbtics center cflength cframe_flag cnonmet_flag color color_bar color_bar_tics colorbox columns commutative complex cone context contexts contour contour_levels cosnpiflag ctaypov ctaypt ctayswitch ctayvar ct_coords ctorsion_flag ctrgsimp cube current_let_rule_package cylinder data_file_name debugmode decreasing default_let_rule_package delay dependencies derivabbrev derivsubst detout diagmetric diff dim dimensions dispflag display2d|10 display_format_internal distribute_over doallmxops domain domxexpt domxmxops domxnctimes dontfactor doscmxops doscmxplus dot0nscsimp dot0simp dot1simp dotassoc dotconstrules dotdistrib dotexptsimp dotident dotscrules draw_graph_program draw_realpart edge_color edge_coloring edge_partition edge_type edge_width %edispflag elevation %emode endphi endtheta engineering_format_floats enhanced3d %enumer epsilon_lp erfflag erf_representation errormsg error_size error_syms error_type %e_to_numlog eval even evenfun evflag evfun ev_point expandwrt_denom expintexpand expintrep expon expop exptdispflag exptisolate exptsubst facexpand facsum_combine factlim factorflag factorial_expand factors_only fb feature features file_name file_output_append file_search_demo file_search_lisp file_search_maxima|10 file_search_tests file_search_usage file_type_lisp file_type_maxima|10 fill_color fill_density filled_func fixed_vertices flipflag float2bf font font_size fortindent fortspaces fpprec fpprintprec functions gamma_expand gammalim gdet genindex gensumnum GGFCFMAX GGFINFINITY globalsolve gnuplot_command gnuplot_curve_styles gnuplot_curve_titles gnuplot_default_term_command gnuplot_dumb_term_command gnuplot_file_args gnuplot_file_name gnuplot_out_file gnuplot_pdf_term_command gnuplot_pm3d gnuplot_png_term_command gnuplot_postamble gnuplot_preamble gnuplot_ps_term_command gnuplot_svg_term_command gnuplot_term gnuplot_view_args Gosper_in_Zeilberger gradefs grid grid2d grind halfangles head_angle head_both head_length head_type height hypergeometric_representation %iargs ibase icc1 icc2 icounter idummyx ieqnprint ifb ifc1 ifc2 ifg ifgi ifr iframe_bracket_form ifri igeowedge_flag ikt1 ikt2 imaginary inchar increasing infeval infinity inflag infolists inm inmc1 inmc2 intanalysis integer integervalued integrate_use_rootsof integration_constant integration_constant_counter interpolate_color intfaclim ip_grid ip_grid_in irrational isolate_wrt_times iterations itr julia_parameter %k1 %k2 keepfloat key key_pos kinvariant kt label label_alignment label_orientation labels lassociative lbfgs_ncorrections lbfgs_nfeval_max leftjust legend letrat let_rule_packages lfg lg lhospitallim limsubst linear linear_solver linechar linel|10 linenum line_type linewidth line_width linsolve_params linsolvewarn lispdisp listarith listconstvars listdummyvars lmxchar load_pathname loadprint logabs logarc logcb logconcoeffp logexpand lognegint logsimp logx logx_secondary logy logy_secondary logz lriem m1pbranch macroexpansion macros mainvar manual_demo maperror mapprint matrix_element_add matrix_element_mult matrix_element_transpose maxapplydepth maxapplyheight maxima_tempdir|10 maxima_userdir|10 maxnegex MAX_ORD maxposex maxpsifracdenom maxpsifracnum maxpsinegint maxpsiposint maxtayorder mesh_lines_color method mod_big_prime mode_check_errorp mode_checkp mode_check_warnp mod_test mod_threshold modular_linear_solver modulus multiplicative multiplicities myoptions nary negdistrib negsumdispflag newline newtonepsilon newtonmaxiter nextlayerfactor niceindicespref nm nmc noeval nolabels nonegative_lp noninteger nonscalar noun noundisp nouns np npi nticks ntrig numer numer_pbranch obase odd oddfun opacity opproperties opsubst optimprefix optionset orientation origin orthopoly_returns_intervals outative outchar packagefile palette partswitch pdf_file pfeformat phiresolution %piargs piece pivot_count_sx pivot_max_sx plot_format plot_options plot_realpart png_file pochhammer_max_index points pointsize point_size points_joined point_type poislim poisson poly_coefficient_ring poly_elimination_order polyfactor poly_grobner_algorithm poly_grobner_debug poly_monomial_order poly_primary_elimination_order poly_return_term_list poly_secondary_elimination_order poly_top_reduction_only posfun position powerdisp pred prederror primep_number_of_tests product_use_gamma program programmode promote_float_to_bigfloat prompt proportional_axes props psexpand ps_file radexpand radius radsubstflag rassociative ratalgdenom ratchristof ratdenomdivide rateinstein ratepsilon ratfac rational ratmx ratprint ratriemann ratsimpexpons ratvarswitch ratweights ratweyl ratwtlvl real realonly redraw refcheck resolution restart resultant ric riem rmxchar %rnum_list rombergabs rombergit rombergmin rombergtol rootsconmode rootsepsilon run_viewer same_xy same_xyz savedef savefactors scalar scalarmatrixp scale scale_lp setcheck setcheckbreak setval show_edge_color show_edges show_edge_type show_edge_width show_id show_label showtime show_vertex_color show_vertex_size show_vertex_type show_vertices show_weight simp simplified_output simplify_products simpproduct simpsum sinnpiflag solvedecomposes solveexplicit solvefactors solvenullwarn solveradcan solvetrigwarn space sparse sphere spring_embedding_depth sqrtdispflag stardisp startphi starttheta stats_numer stringdisp structures style sublis_apply_lambda subnumsimp sumexpand sumsplitfact surface surface_hide svg_file symmetric tab taylordepth taylor_logexpand taylor_order_coefficients taylor_truncate_polynomials tensorkill terminal testsuite_files thetaresolution timer_devalue title tlimswitch tr track transcompile transform transform_xy translate_fast_arrays transparent transrun tr_array_as_ref tr_bound_function_applyp tr_file_tty_messagesp tr_float_can_branch_complex tr_function_call_default trigexpandplus trigexpandtimes triginverses trigsign trivial_solutions tr_numer tr_optimize_max_loop tr_semicompile tr_state_vars tr_warn_bad_function_calls tr_warn_fexpr tr_warn_meval tr_warn_mode tr_warn_undeclared tr_warn_undefined_variable tstep ttyoff tube_extremes ufg ug %unitexpand unit_vectors uric uriem use_fast_arrays user_preamble usersetunits values vect_cross verbose vertex_color vertex_coloring vertex_partition vertex_size vertex_type view warnings weyl width windowname windowtitle wired_surface wireframe xaxis xaxis_color xaxis_secondary xaxis_type xaxis_width xlabel xlabel_secondary xlength xrange xrange_secondary xtics xtics_axis xtics_rotate xtics_rotate_secondary xtics_secondary xtics_secondary_axis xu_grid x_voxel xy_file xyplane xy_scale yaxis yaxis_color yaxis_secondary yaxis_type yaxis_width ylabel ylabel_secondary ylength yrange yrange_secondary ytics ytics_axis ytics_rotate ytics_rotate_secondary ytics_secondary ytics_secondary_axis yv_grid y_voxel yx_ratio zaxis zaxis_color zaxis_type zaxis_width zeroa zerob zerobern zeta%pi zlabel zlabel_rotate zlength zmin zn_primroot_limit zn_primroot_pretest",
@@ -325,13 +326,14 @@
 literal:"admin all auto both bottom bzip2 colored components current custom directory false force hide highest ifdiff ifnewer instfiles lastused leave left license listonly lzma nevershow none normal notset off on open print right show silent silentlog smooth textonly top true try un.components un.custom un.directory un.instfiles un.license uninstConfirm user Win10 Win7 Win8 WinVista zlib"},contains:[a.HASH_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.COMMENT(";","$",{relevance:0}),{className:"function",
 beginKeywords:"Function PageEx Section SectionGroup",end:"$"},e,{className:"keyword",begin:/!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversion|gettlbversion|if|ifdef|ifmacrodef|ifmacrondef|ifndef|include|insertmacro|macro|macroend|makensis|packhdr|searchparse|searchreplace|system|tempfile|undef|verbose|warning)/},b,c,d,{className:"params",begin:"(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)"},
 {className:"class",begin:/\w+::\w+/},a.NUMBER_MODE]}});b.registerLanguage("objectivec",function(a){var b=/[a-zA-Z@][a-zA-Z0-9_]*/;return{aliases:["mm","objc","obj-c"],keywords:{keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",
-literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},lexemes:b,illegal:"</",contains:[{className:"built_in",begin:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.C_NUMBER_MODE,a.QUOTE_STRING_MODE,{className:"string",variants:[{begin:'@"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:"'",end:"[^\\\\]'",illegal:"[^\\\\][^']"}]},
-{className:"meta",begin:"#",end:"$",contains:[{className:"meta-string",variants:[{begin:'"',end:'"'},{begin:"<",end:">"}]}]},{className:"class",begin:"(@interface|@class|@protocol|@implementation)\\b",end:"({|$)",excludeEnd:!0,keywords:"@interface @class @protocol @implementation",lexemes:b,contains:[a.UNDERSCORE_TITLE_MODE]},{begin:"\\."+a.UNDERSCORE_IDENT_RE,relevance:0}]}});b.registerLanguage("ocaml",function(a){return{aliases:["ml"],keywords:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",
-built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",literal:"true false"},illegal:/\/\/|>>/,lexemes:"[a-z_]\\w*!?",contains:[{className:"literal",begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},a.COMMENT("\\(\\*","\\*\\)",{contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{className:"type",begin:"`[A-Z][\\w']*"},{className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0},
-a.inherit(a.APOS_STRING_MODE,{className:"string",relevance:0}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null}),{className:"number",begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",relevance:0},{begin:/[-=]>/}]}});b.registerLanguage("openscad",function(a){var b={className:"keyword",begin:"\\$(f[asn]|t|vp[rtd]|children)"},c={className:"number",begin:"\\b\\d+(\\.\\d+)?(e-?\\d+)?",relevance:0},d=a.inherit(a.QUOTE_STRING_MODE,
-{illegal:null});return{aliases:["scad"],keywords:{keyword:"function module include use for intersection_for if else \\%",literal:"false true PI undef",built_in:"circle square polygon text sphere cube cylinder polyhedron translate rotate scale resize mirror multmatrix color offset hull minkowski union difference intersection abs sign sin cos tan acos asin atan atan2 floor round ceil ln log pow sqrt exp rands min max concat lookup str chr search version version_num norm cross parent_module echo import import_dxf dxf_linear_extrude linear_extrude rotate_extrude surface projection render children dxf_cross dxf_dim let assign"},
-contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,c,{className:"meta",keywords:{"meta-keyword":"include use"},begin:"include|use <",end:">"},d,b,{begin:"[*!#%]",relevance:0},{className:"function",beginKeywords:"module function",end:"\\=|\\{",contains:[{className:"params",begin:"\\(",end:"\\)",contains:["self",c,d,b,{className:"literal",begin:"false|true|PI|undef"}]},a.UNDERSCORE_TITLE_MODE]}]}});b.registerLanguage("oxygene",function(a){var b=a.COMMENT("{","}",{relevance:0}),c=a.COMMENT("\\(\\*",
-"\\*\\)",{relevance:10}),d={className:"string",begin:"'",end:"'",contains:[{begin:"''"}]},e={className:"string",begin:"(#\\d+)+"},g={className:"function",beginKeywords:"function constructor destructor procedure method",end:"[:;]",keywords:"function constructor|10 destructor|10 procedure|10 method|10",contains:[a.TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",keywords:"abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",
+literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},lexemes:b,illegal:"</",contains:[{className:"built_in",begin:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.C_NUMBER_MODE,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,{className:"string",variants:[{begin:'@"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]}]},{className:"meta",begin:/#\s*[a-z]+\b/,
+end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},a.inherit(a.QUOTE_STRING_MODE,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"(@interface|@class|@protocol|@implementation)\\b",end:"({|$)",excludeEnd:!0,keywords:"@interface @class @protocol @implementation",lexemes:b,contains:[a.UNDERSCORE_TITLE_MODE]},
+{begin:"\\."+a.UNDERSCORE_IDENT_RE,relevance:0}]}});b.registerLanguage("ocaml",function(a){return{aliases:["ml"],keywords:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",
+literal:"true false"},illegal:/\/\/|>>/,lexemes:"[a-z_]\\w*!?",contains:[{className:"literal",begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},a.COMMENT("\\(\\*","\\*\\)",{contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{className:"type",begin:"`[A-Z][\\w']*"},{className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0},a.inherit(a.APOS_STRING_MODE,{className:"string",relevance:0}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null}),{className:"number",
+begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",relevance:0},{begin:/[-=]>/}]}});b.registerLanguage("openscad",function(a){var b={className:"keyword",begin:"\\$(f[asn]|t|vp[rtd]|children)"},c={className:"number",begin:"\\b\\d+(\\.\\d+)?(e-?\\d+)?",relevance:0},d=a.inherit(a.QUOTE_STRING_MODE,{illegal:null});return{aliases:["scad"],keywords:{keyword:"function module include use for intersection_for if else \\%",literal:"false true PI undef",
+built_in:"circle square polygon text sphere cube cylinder polyhedron translate rotate scale resize mirror multmatrix color offset hull minkowski union difference intersection abs sign sin cos tan acos asin atan atan2 floor round ceil ln log pow sqrt exp rands min max concat lookup str chr search version version_num norm cross parent_module echo import import_dxf dxf_linear_extrude linear_extrude rotate_extrude surface projection render children dxf_cross dxf_dim let assign"},contains:[a.C_LINE_COMMENT_MODE,
+a.C_BLOCK_COMMENT_MODE,c,{className:"meta",keywords:{"meta-keyword":"include use"},begin:"include|use <",end:">"},d,b,{begin:"[*!#%]",relevance:0},{className:"function",beginKeywords:"module function",end:"\\=|\\{",contains:[{className:"params",begin:"\\(",end:"\\)",contains:["self",c,d,b,{className:"literal",begin:"false|true|PI|undef"}]},a.UNDERSCORE_TITLE_MODE]}]}});b.registerLanguage("oxygene",function(a){var b=a.COMMENT("{","}",{relevance:0}),c=a.COMMENT("\\(\\*","\\*\\)",{relevance:10}),d={className:"string",
+begin:"'",end:"'",contains:[{begin:"''"}]},e={className:"string",begin:"(#\\d+)+"},g={className:"function",beginKeywords:"function constructor destructor procedure method",end:"[:;]",keywords:"function constructor|10 destructor|10 procedure|10 method|10",contains:[a.TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",keywords:"abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",
 contains:[d,e]},b,c]};return{case_insensitive:!0,lexemes:/\.?\w+/,keywords:"abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",
 illegal:'("|\\$[G-Zg-z]|\\/\\*|</|=>|->)',contains:[b,c,a.C_LINE_COMMENT_MODE,d,e,a.NUMBER_MODE,g,{className:"class",begin:"=\\bclass\\b",end:"end;",keywords:"abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",
 contains:[d,e,b,c,a.C_LINE_COMMENT_MODE,g]}]}});b.registerLanguage("parser3",function(a){var b=a.COMMENT("{","}",{contains:["self"]});return{subLanguage:"xml",relevance:0,contains:[a.COMMENT("^#","$"),a.COMMENT("\\^rem{","}",{relevance:10,contains:[b]}),{className:"meta",begin:"^@(?:BASE|USE|CLASS|OPTIONS)$",relevance:10},{className:"title",begin:"@[\\w\\-]+\\[[\\w^;\\-]*\\](?:\\[[\\w^;\\-]*\\])?(?:.*)$"},{className:"variable",begin:"\\$\\{?[\\w\\-\\.\\:]+\\}?"},{className:"keyword",begin:"\\^[\\w\\-\\.\\:]+"},
diff --git a/lib/jetty/BUILD b/lib/jetty/BUILD
index 6417385..fe07794 100644
--- a/lib/jetty/BUILD
+++ b/lib/jetty/BUILD
@@ -21,7 +21,6 @@
     data = ["//lib:LICENSE-Apache2.0"],
     visibility = ["//visibility:public"],
     exports = [
-        ":continuation",
         ":http",
         "@jetty-server//jar",
     ],
@@ -32,20 +31,12 @@
     data = ["//lib:LICENSE-Apache2.0"],
     visibility = ["//visibility:public"],
     exports = [
-        ":continuation",
         ":http",
         "@jetty-jmx//jar",
     ],
 )
 
 java_library(
-    name = "continuation",
-    data = ["//lib:LICENSE-Apache2.0"],
-    visibility = ["//visibility:public"],
-    exports = ["@jetty-continuation//jar"],
-)
-
-java_library(
     name = "http",
     data = ["//lib:LICENSE-Apache2.0"],
     visibility = ["//visibility:public"],
diff --git a/lib/nongoogle_test.sh b/lib/nongoogle_test.sh
index 23b40ad..dcf40f0 100755
--- a/lib/nongoogle_test.sh
+++ b/lib/nongoogle_test.sh
@@ -11,7 +11,36 @@
 grep 'name = "[^"]*"' ${bzl} | sed 's|^[^"]*"||g;s|".*$||g' | sort > $TMP/names
 
 cat << EOF > $TMP/want
+cglib-3_2
+dropwizard-core
+duct-tape
+eddsa
+elasticsearch-rest-client
+httpasyncclient
+httpcore-nio
+j2objc
+jackson-core
+javassist
+jna
+jruby
+mina-core
+nekohtml
+objenesis
+openid-consumer
+powermock-api-easymock
+powermock-api-support
+powermock-core
+powermock-module-junit4
+powermock-module-junit4-common
+powermock-reflect
+sshd
+sshd-common
+sshd-mina
+testcontainers
+testcontainers-elasticsearch
 tukaani-xz
+visible-assertions
+xerces
 EOF
 
 diff -u $TMP/names $TMP/want
diff --git a/modules/jgit b/modules/jgit
index 6bae5a8..0356613 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 6bae5a88bc4583e00d1a47758956eae2b5d59e4c
+Subproject commit 0356613f48ebee2e3d2d65780e71d9e0b43a752e
diff --git a/package.json b/package.json
index 8fb3d3d..5ed4671 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
     "eslint-config-google": "^0.13.0",
     "eslint-plugin-html": "^6.0.0",
     "fried-twinkie": "^0.2.2",
-    "polylint": "^2.10.4",
+    "polymer-cli": "^1.9.11",
     "typescript": "^2.x.x",
     "web-component-tester": "^6.5.0"
   },
diff --git a/plugins/delete-project b/plugins/delete-project
index 881e409..38f4fde 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit 881e409080a7a257175e736b952ab78dab51be9d
+Subproject commit 38f4fde24ce24cf1bf8d1e4d074f1d784ed983b8
diff --git a/plugins/hooks b/plugins/hooks
index 71cdc88..f4bf0ff 160000
--- a/plugins/hooks
+++ b/plugins/hooks
@@ -1 +1 @@
-Subproject commit 71cdc88f4804a4811e613d8679862cb33dd75cc1
+Subproject commit f4bf0ffbd13a748cc46a3368a8fadcc2cbab6e21
diff --git a/plugins/plugin-manager b/plugins/plugin-manager
index d486f1e..828d666 160000
--- a/plugins/plugin-manager
+++ b/plugins/plugin-manager
@@ -1 +1 @@
-Subproject commit d486f1edac54c63c46f92c93fa15958f89cfe60f
+Subproject commit 828d666bbb4aae1a2c348a12d7855ec5db3be46f
diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md
index a73f243..461e2b9 100644
--- a/polygerrit-ui/README.md
+++ b/polygerrit-ui/README.md
@@ -64,14 +64,16 @@
 The biggest draw back of this method is that you cannot log in, so cannot test
 scenarios that require it.
 
-#### MITM Proxy
+#### Chrome extension: Gerrit FE Dev Helper
 
-[MITM Proxy](https://mitmproxy.org/) is an open source product for proxying
-https servers. The
-[contrib/mitm-ui/](https://gerrit.googlesource.com/gerrit/+/master/contrib/mitm-ui/)
-directory contains scripts (and documentation) for using this technology
-(instead of the Go server). These scripts are somewhat experimental and
-unmaintained though.
+To be able to bypass the auth and also help improve the productivity of Gerrit FE developers,
+we created this chrome extension: [Gerrit FE Dev Helper](https://chrome.google.com/webstore/detail/gerrit-fe-dev-helper/jimgomcnodkialnpmienbomamgomglkd).
+
+It basically works as a proxy that will block / redirect requests from current sites to any given url base on certain rules.
+
+The source code is in [Gerrit - gerrit-fe-dev-helper](https://gerrit-review.googlesource.com/q/project:gerrit-fe-dev-helper), contributions are welcomed!
+
+To use this extension, just follow its [readme here](https://gerrit.googlesource.com/gerrit-fe-dev-helper/+/master/README.md).
 
 ## Running locally against a Gerrit test site
 
@@ -182,6 +184,11 @@
 ```
 
 ## Template Type Safety
+
+> **Warning**: This feature is temporary disabled, because it doesn't work with Polymer 2 and Polymer 3. 
+Some of the checks are made by polymer linter.
+
+
 Polymer elements are not type checked against the element definition, making it
 trivial to break the display when refactoring or moving code. We now run
 additional tests to help ensure that template types are checked.
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 6d30a14..5ff820b 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -46,6 +46,23 @@
 )
 
 filegroup(
+    name = "pg_code_without_test",
+    srcs = glob(
+        [
+            "**/*.html",
+            "**/*.js",
+        ],
+        exclude = [
+            "bower_components/**",
+            "**/*_test.html",
+            "embed/test.html",
+            "test/**",
+            "samples/**",
+        ],
+    ),
+)
+
+filegroup(
     name = "bower_components",
     srcs = glob(
         [
@@ -108,7 +125,8 @@
     size = "large",
     srcs = ["polylint_test.sh"],
     data = [
-        ":pg_code",
+        "polymer.json",
+        ":pg_code_without_test",
         "//polygerrit-ui:polygerrit_components.bower_components.zip",
     ],
     # Should not run sandboxed.
diff --git a/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior.html b/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior.html
index 36e0201..f560ea8 100644
--- a/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior.html
+++ b/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior.html
@@ -45,5 +45,22 @@
       });
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.AsyncForeachMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior_test.html b/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior_test.html
index 970bfc7..03ba6b1 100644
--- a/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/async-foreach-behavior/async-foreach-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>async-foreach-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
index 1748647..92596e0 100644
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior.html
@@ -28,5 +28,22 @@
       return window.CANONICAL_PATH || '';
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.BaseUrlMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
index b61b142..5669bc4 100644
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>base-url-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior.html b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior.html
index 4e25530..3361bc8 100644
--- a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior.html
+++ b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior.html
@@ -58,5 +58,22 @@
   },
   Gerrit.BaseUrlBehavior,
   ];
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.DocsUrlMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html
index 2c513f3..e554012 100644
--- a/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/docs-url-behavior/docs-url-behavior_test.html
@@ -19,7 +19,7 @@
 <script src="/bower_components/web-component-tester/browser.js"></script>
 <link rel="import" href="../../test/common-test-setup.html"/>
 <title>docs-url-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <link rel="import" href="docs-url-behavior.html">
diff --git a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior.html b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior.html
index 2d25b29..5daa032 100644
--- a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior.html
+++ b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior.html
@@ -42,5 +42,22 @@
       return isDescendant;
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.DomUtilMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html
index 8323ac6..a52e0e2 100644
--- a/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/dom-util-behavior/dom-util-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>dom-util-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/fire-behavior/fire-behavior.html b/polygerrit-ui/app/behaviors/fire-behavior/fire-behavior.html
index b5afab1..5b3d420 100644
--- a/polygerrit-ui/app/behaviors/fire-behavior/fire-behavior.html
+++ b/polygerrit-ui/app/behaviors/fire-behavior/fire-behavior.html
@@ -51,5 +51,22 @@
       return event;
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.FireMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior.html b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior.html
index 0c75c44..9d3b1af 100644
--- a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior.html
@@ -150,5 +150,29 @@
       });
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.AccessMixin = base =>
+      class extends base {
+        static get properties() {
+          return {
+            permissionValues: {
+              type: Object,
+            },
+          };
+        }
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html
index 0d1ee57..48565a6 100644
--- a/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-access-behavior/gr-access-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html
index 182d242..07350b9 100644
--- a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior.html
@@ -201,5 +201,22 @@
       };
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.AdminNavMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html
index 90593a2..25b75c8 100644
--- a/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-admin-nav-behavior/gr-admin-nav-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.html b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.html
index c462c6f..db35a67 100644
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior.html
@@ -75,5 +75,31 @@
       return newColumns;
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.ChangeTableMixin = base =>
+      class extends base {
+        static get properties() {
+          return {
+            columnNames: {
+              type: Array,
+            },
+          };
+        }
+
+        isColumnHidden(columnToCheck, columnsToDisplay) {}
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
index 791e2af..52931bc 100644
--- a/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-change-table-behavior/gr-change-table-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.html b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.html
index 3106fc8..e5ded0e 100644
--- a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior.html
@@ -39,5 +39,22 @@
       return GrDisplayNameUtils.getGroupDisplayName(group);
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.DisplayNameMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html
index 3d4eca1..aa217a1 100644
--- a/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-display-name-behavior/gr-display-name-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-display-name-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior.html b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior.html
index b6edb57..06912d5 100644
--- a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior.html
@@ -59,5 +59,26 @@
   Gerrit.BaseUrlBehavior,
   Gerrit.URLEncodingBehavior,
   ];
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.ListViewMixin = base =>
+      class extends base {
+        computeLoadingClass(loading) {}
+
+        computeShownItems(items) {}
+      };
+  }
 })(window);
+
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html
index 535483d..9b48cdc 100644
--- a/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-list-view-behavior/gr-list-view-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html
index 5942833..c2ca081 100644
--- a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html
@@ -31,7 +31,7 @@
 
   window.Gerrit = window.Gerrit || {};
 
-  /** @polymerBehavior this */
+  /** @polymerBehavior Gerrit.PatchSetBehavior*/
   Gerrit.PatchSetBehavior = {
     EDIT_NAME: 'edit',
     PARENT_NAME: 'PARENT',
@@ -272,5 +272,29 @@
       return -parseInt(rangeBase + '', 10);
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.PatchSetMixin = base =>
+      class extends base {
+        computeLatestPatchNum(allPatchSets) {}
+
+        hasEditPatchsetLoaded(patchRangeRecord) {}
+
+        hasEditBasedOnCurrentPatchSet(allPatchSets) {}
+
+        computeAllPatchSets(change) {}
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html
index 3db4084..5e70179 100644
--- a/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-patch-set-behavior/gr-patch-set-behavior_test.html
@@ -19,7 +19,7 @@
 <script src="/bower_components/web-component-tester/browser.js"></script>
 <link rel="import" href="../../test/common-test-setup.html"/>
 <title>gr-patch-set-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <link rel="import" href="gr-patch-set-behavior.html">
diff --git a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior.html b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior.html
index 5e597ae..8f9bf00 100644
--- a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior.html
@@ -110,5 +110,25 @@
       return `\u2026/${pathPieces.slice(index).join('/')}`;
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.PathListMixin = base =>
+      class extends base {
+        computeDisplayPath(path) {}
+
+        computeTruncatedPath(path) {}
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html
index 0046290..924c98c 100644
--- a/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-path-list-behavior/gr-path-list-behavior_test.html
@@ -19,7 +19,7 @@
 <script src="/bower_components/web-component-tester/browser.js"></script>
 <link rel="import" href="../../test/common-test-setup.html"/>
 <title>gr-path-list-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <link rel="import" href="gr-path-list-behavior.html">
diff --git a/polygerrit-ui/app/behaviors/gr-repo-plugin-config-behavior/gr-repo-plugin-config-behavior.html b/polygerrit-ui/app/behaviors/gr-repo-plugin-config-behavior/gr-repo-plugin-config-behavior.html
index 2dc070d..69ebf23 100644
--- a/polygerrit-ui/app/behaviors/gr-repo-plugin-config-behavior/gr-repo-plugin-config-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-repo-plugin-config-behavior/gr-repo-plugin-config-behavior.html
@@ -20,7 +20,7 @@
 
   window.Gerrit = window.Gerrit || {};
 
-  /** @polymerBehavior this */
+  /** @polymerBehavior Gerrit.RepoPluginConfig*/
   Gerrit.RepoPluginConfig = {
     // Should be kept in sync with
     // gerrit/java/com/google/gerrit/extensions/api/projects/ProjectConfigEntryType.java.
@@ -34,5 +34,22 @@
     },
     PLUGIN_CONFIG_CHANGED: 'plugin-config-changed',
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.RepoPluginConfigMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js
index 0bf620f..73b8261 100644
--- a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js
+++ b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior.js
@@ -146,4 +146,28 @@
       }
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.TooltipMixin = base =>
+      class extends base {
+        static get properties() {
+          return {
+            hasTooltip: {
+              type: Boolean,
+            },
+          };
+        }
+      };
+  }
 })(window);
diff --git a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html
index 173c8d4..f3354a4 100644
--- a/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-tooltip-behavior/gr-tooltip-behavior_test.html
@@ -17,7 +17,7 @@
 -->
 
 <title>tooltip-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.html b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.html
index 69703f6..c4979b5 100644
--- a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.html
+++ b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior.html
@@ -53,5 +53,22 @@
       return decodeURIComponent(withoutPlus);
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.URLEncodingMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html
index 73e51d3..6cf2c68 100644
--- a/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/gr-url-encoding-behavior/gr-url-encoding-behavior_test.html
@@ -17,7 +17,7 @@
 -->
 
 <title>gr-url-encoding-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
index c75227c..d4e2c72 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html
@@ -463,7 +463,7 @@
 
   window.Gerrit = window.Gerrit || {};
 
-  /** @polymerBehavior KeyboardShortcutBehavior */
+  /** @polymerBehavior Gerrit.KeyboardShortcutBehavior*/
   Gerrit.KeyboardShortcutBehavior = [
     Polymer.IronA11yKeysBehavior,
     {
@@ -612,5 +612,22 @@
       shortcutManager.bindShortcut(shortcut, ...bindings);
     },
   };
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.KeyboardShortcutMixin = base =>
+      class extends base {
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html
index 3183c7e..ba143ec 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
index fbeaa64..27041f7 100644
--- a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
+++ b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior.html
@@ -177,5 +177,25 @@
   },
   Gerrit.BaseUrlBehavior,
   ];
+
+  // eslint-disable-next-line no-unused-vars
+  function defineEmptyMixin() {
+    // This is a temporary function.
+    // Polymer linter doesn't process correctly the following code:
+    // class MyElement extends Polymer.mixinBehaviors([legacyBehaviors], ...) {...}
+    // To workaround this issue, the mock mixin is declared in this method.
+    // In the following changes, legacy behaviors will be converted to mixins.
+
+    /**
+     * @polymer
+     * @mixinFunction
+     */
+    Gerrit.RESTClientMixin = base =>
+      class extends base {
+        changeStatusString(change) {}
+
+        changeStatuses(change, opt_options) {}
+      };
+  }
 })(window);
 </script>
diff --git a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html
index a77a01f..cfcc11e 100644
--- a/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/rest-client-behavior/rest-client-behavior_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>keyboard-shortcut-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html b/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html
index ab446f1..7351647 100644
--- a/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html
+++ b/polygerrit-ui/app/behaviors/safe-types-behavior/safe-types-behavior_test.html
@@ -17,7 +17,7 @@
 -->
 
 <title>safe-types-behavior</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
index ac65360..a52cb1a 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
@@ -86,7 +86,9 @@
         padding-right: var(--spacing-m);
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <fieldset id="section"
         class$="gr-form-styles [[_computeSectionClass(editing, canUpload, ownerOf, _editingRef, _deleted)]]">
       <div id="mainContainer">
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.js b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.js
index afe3955..158e20b 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.js
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.js
@@ -36,61 +36,69 @@
   const ON_BEHALF_OF = '(On Behalf Of)';
   const LABEL = 'Label';
 
-  Polymer({
-    is: 'gr-access-section',
-
-    properties: {
-      capabilities: Object,
-      /** @type {?} */
-      section: {
-        type: Object,
-        notify: true,
-        observer: '_updateSection',
-      },
-      groups: Object,
-      labels: Object,
-      editing: {
-        type: Boolean,
-        value: false,
-        observer: '_handleEditingChanged',
-      },
-      canUpload: Boolean,
-      ownerOf: Array,
-      _originalId: String,
-      _editingRef: {
-        type: Boolean,
-        value: false,
-      },
-      _deleted: {
-        type: Boolean,
-        value: false,
-      },
-      _permissions: Array,
-    },
-
-    behaviors: [
-      Gerrit.AccessBehavior,
-      /**
+  /**
+    * @appliesMixin Gerrit.AccessMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrAccessSection extends Polymer.mixinBehaviors( [
+    Gerrit.AccessBehavior,
+    /**
        * Unused in this element, but called by other elements in tests
        * e.g gr-repo-access_test.
        */
-      Gerrit.FireBehavior,
-    ],
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-access-section'; }
 
-    listeners: {
-      'access-saved': '_handleAccessSaved',
-    },
+    static get properties() {
+      return {
+        capabilities: Object,
+        /** @type {?} */
+        section: {
+          type: Object,
+          notify: true,
+          observer: '_updateSection',
+        },
+        groups: Object,
+        labels: Object,
+        editing: {
+          type: Boolean,
+          value: false,
+          observer: '_handleEditingChanged',
+        },
+        canUpload: Boolean,
+        ownerOf: Array,
+        _originalId: String,
+        _editingRef: {
+          type: Boolean,
+          value: false,
+        },
+        _deleted: {
+          type: Boolean,
+          value: false,
+        },
+        _permissions: Array,
+      };
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('access-saved',
+          () => this._handleAccessSaved());
+    }
 
     _updateSection(section) {
       this._permissions = this.toSortedArray(section.value.permissions);
       this._originalId = section.id;
-    },
+    }
 
     _handleAccessSaved() {
       // Set a new 'original' value to keep track of after the value has been
       // saved.
       this._updateSection(this.section);
-    },
+    }
 
     _handleValueChange() {
       if (!this.section.value.added) {
@@ -103,7 +111,7 @@
             'access-modified', {bubbles: true, composed: true}));
       }
       this.section.value.updatedId = this.section.id;
-    },
+    }
 
     _handleEditingChanged(editing, editingOld) {
       // Ignore when editing gets set initially.
@@ -123,7 +131,7 @@
           }
         }
       }
-    },
+    }
 
     _computePermissions(name, capabilities, labels) {
       let allPermissions;
@@ -140,17 +148,17 @@
       return allPermissions.filter(permission => {
         return !this.section.value.permissions[permission.id];
       });
-    },
+    }
 
     _computeHideEditClass(section) {
       return section.id === 'GLOBAL_CAPABILITIES' ? 'hide' : '';
-    },
+    }
 
     _handleAddedPermissionRemoved(e) {
       const index = e.model.index;
       this._permissions = this._permissions.slice(0, index).concat(
           this._permissions.slice(index + 1, this._permissions.length));
-    },
+    }
 
     _computeLabelOptions(labels) {
       const labelOptions = [];
@@ -172,7 +180,7 @@
         });
       }
       return labelOptions;
-    },
+    }
 
     _computePermissionName(name, permission, permissionValues, capabilities) {
       if (name === GLOBAL_NAME) {
@@ -186,7 +194,7 @@
         }
         return `${LABEL} ${permission.value.label}${behalfOf}`;
       }
-    },
+    }
 
     _computeSectionName(name) {
       // When a new section is created, it doesn't yet have a ref. Set into
@@ -204,7 +212,7 @@
         return `Reference: ${name}`;
       }
       return name;
-    },
+    }
 
     _handleRemoveReference() {
       if (this.section.value.added) {
@@ -215,27 +223,27 @@
       this.section.value.deleted = true;
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _handleUndoRemove() {
       this._deleted = false;
       delete this.section.value.deleted;
-    },
+    }
 
     editRefInput() {
       return Polymer.dom(this.root).querySelector(Polymer.Element ?
         'iron-input.editRefInput' :
         'input[is=iron-input].editRefInput');
-    },
+    }
 
     editReference() {
       this._editingRef = true;
       this.editRefInput().focus();
-    },
+    }
 
     _isEditEnabled(canUpload, ownerOf, sectionId) {
       return canUpload || (ownerOf && ownerOf.indexOf(sectionId) >= 0);
-    },
+    }
 
     _computeSectionClass(editing, canUpload, ownerOf, editingRef, deleted) {
       const classList = [];
@@ -249,11 +257,11 @@
         classList.push('deleted');
       }
       return classList.join(' ');
-    },
+    }
 
     _computeEditBtnClass(name) {
       return name === GLOBAL_NAME ? 'global' : '';
-    },
+    }
 
     _handleAddPermission() {
       const value = this.$.permissionSelect.value;
@@ -286,6 +294,8 @@
       this.push('_permissions', permission);
       this.set(['section.value.permissions', permission.id],
           permission.value);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccessSection.is, GrAccessSection);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.html b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.html
index 16c654f..55b2495 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-access-section</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.html b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.html
index bf1086c..5207717 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.html
@@ -30,8 +30,12 @@
 
 <dom-module id="gr-admin-group-list">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-table-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <gr-list-view
         create-new="[[_createNewCapability]]"
         filter="[[_filter]]"
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
index 74dcb87..e387724 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list.js
@@ -17,65 +17,72 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-admin-group-list',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.ListViewMixin
+    */
+  class GrAdminGroupList extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.ListViewBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-admin-group-list'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      /**
+        /**
        * Offset of currently visible query results.
        */
-      _offset: Number,
-      _path: {
-        type: String,
-        readOnly: true,
-        value: '/admin/groups',
-      },
-      _hasNewGroupName: Boolean,
-      _createNewCapability: {
-        type: Boolean,
-        value: false,
-      },
-      _groups: Array,
+        _offset: Number,
+        _path: {
+          type: String,
+          readOnly: true,
+          value: '/admin/groups',
+        },
+        _hasNewGroupName: Boolean,
+        _createNewCapability: {
+          type: Boolean,
+          value: false,
+        },
+        _groups: Array,
 
-      /**
+        /**
        * Because  we request one more than the groupsPerPage, _shownGroups
        * may be one less than _groups.
        * */
-      _shownGroups: {
-        type: Array,
-        computed: 'computeShownItems(_groups)',
-      },
+        _shownGroups: {
+          type: Array,
+          computed: 'computeShownItems(_groups)',
+        },
 
-      _groupsPerPage: {
-        type: Number,
-        value: 25,
-      },
+        _groupsPerPage: {
+          type: Number,
+          value: 25,
+        },
 
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _filter: String,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.ListViewBehavior,
-    ],
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _filter: String,
+      };
+    }
 
     attached() {
+      super.attached();
       this._getCreateGroupCapability();
       this.fire('title-change', {title: 'Groups'});
       this._maybeOpenCreateOverlay(this.params);
-    },
+    }
 
     _paramsChanged(params) {
       this._loading = true;
@@ -84,7 +91,7 @@
 
       return this._getGroups(this._filter, this._groupsPerPage,
           this._offset);
-    },
+    }
 
     /**
      * Opens the create overlay if the route has a hash 'create'
@@ -94,11 +101,11 @@
       if (params && params.openCreateModal) {
         this.$.createOverlay.open();
       }
-    },
+    }
 
     _computeGroupUrl(id) {
       return Gerrit.Nav.getUrlForGroup(id);
-    },
+    }
 
     _getCreateGroupCapability() {
       return this.$.restAPI.getAccount().then(account => {
@@ -110,7 +117,7 @@
               }
             });
       });
-    },
+    }
 
     _getGroups(filter, groupsPerPage, offset) {
       this._groups = [];
@@ -127,30 +134,32 @@
                 });
             this._loading = false;
           });
-    },
+    }
 
     _refreshGroupsList() {
       this.$.restAPI.invalidateGroupsCache();
       return this._getGroups(this._filter, this._groupsPerPage,
           this._offset);
-    },
+    }
 
     _handleCreateGroup() {
       this.$.createNewModal.handleCreateGroup().then(() => {
         this._refreshGroupsList();
       });
-    },
+    }
 
     _handleCloseCreate() {
       this.$.createOverlay.close();
-    },
+    }
 
     _handleCreateClicked() {
       this.$.createOverlay.open();
-    },
+    }
 
     _visibleToAll(item) {
       return item.options.visible_to_all === true ? 'Y' : 'N';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAdminGroupList.is, GrAdminGroupList);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html
index 58c7be4..455b3a2 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-group-list/gr-admin-group-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-admin-group-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html
index c7187a9..aae11d3 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.html
@@ -43,8 +43,12 @@
 
 <dom-module id="gr-admin-view">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-menu-page-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-menu-page-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-page-nav-styles">
       gr-dropdown-list {
         --trigger-style: {
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js
index aa9cb00..23c7ae0 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.js
@@ -19,63 +19,73 @@
 
   const INTERNAL_GROUP_REGEX = /^[\da-f]{40}$/;
 
-  Polymer({
-    is: 'gr-admin-view',
+  /**
+    * @appliesMixin Gerrit.AdminNavMixin
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrAdminView extends Polymer.mixinBehaviors( [
+    Gerrit.AdminNavBehavior,
+    Gerrit.BaseUrlBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-admin-view'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      params: Object,
-      path: String,
-      adminView: String,
+        params: Object,
+        path: String,
+        adminView: String,
 
-      _breadcrumbParentName: String,
-      _repoName: String,
-      _groupId: {
-        type: Number,
-        observer: '_computeGroupName',
-      },
-      _groupIsInternal: Boolean,
-      _groupName: String,
-      _groupOwner: {
-        type: Boolean,
-        value: false,
-      },
-      _subsectionLinks: Array,
-      _filteredLinks: Array,
-      _showDownload: {
-        type: Boolean,
-        value: false,
-      },
-      _isAdmin: {
-        type: Boolean,
-        value: false,
-      },
-      _showGroup: Boolean,
-      _showGroupAuditLog: Boolean,
-      _showGroupList: Boolean,
-      _showGroupMembers: Boolean,
-      _showRepoAccess: Boolean,
-      _showRepoCommands: Boolean,
-      _showRepoDashboards: Boolean,
-      _showRepoDetailList: Boolean,
-      _showRepoMain: Boolean,
-      _showRepoList: Boolean,
-      _showPluginList: Boolean,
-    },
+        _breadcrumbParentName: String,
+        _repoName: String,
+        _groupId: {
+          type: Number,
+          observer: '_computeGroupName',
+        },
+        _groupIsInternal: Boolean,
+        _groupName: String,
+        _groupOwner: {
+          type: Boolean,
+          value: false,
+        },
+        _subsectionLinks: Array,
+        _filteredLinks: Array,
+        _showDownload: {
+          type: Boolean,
+          value: false,
+        },
+        _isAdmin: {
+          type: Boolean,
+          value: false,
+        },
+        _showGroup: Boolean,
+        _showGroupAuditLog: Boolean,
+        _showGroupList: Boolean,
+        _showGroupMembers: Boolean,
+        _showRepoAccess: Boolean,
+        _showRepoCommands: Boolean,
+        _showRepoDashboards: Boolean,
+        _showRepoDetailList: Boolean,
+        _showRepoMain: Boolean,
+        _showRepoList: Boolean,
+        _showPluginList: Boolean,
+      };
+    }
 
-    behaviors: [
-      Gerrit.AdminNavBehavior,
-      Gerrit.BaseUrlBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    observers: [
-      '_paramsChanged(params)',
-    ],
+    static get observers() {
+      return [
+        '_paramsChanged(params)',
+      ];
+    }
 
     attached() {
+      super.attached();
       this.reload();
-    },
+    }
 
     reload() {
       const promises = [
@@ -123,18 +133,18 @@
                   });
             });
       });
-    },
+    }
 
     _computeSelectValue(params) {
       if (!params || !params.view) { return; }
       return params.view + (params.detail || '');
-    },
+    }
 
     _selectedIsCurrentPage(selected) {
       return (selected.parent === (this._repoName || this._groupId) &&
           selected.view === this.params.view &&
           selected.detailType === this.params.detail);
-    },
+    }
 
     _handleSubsectionChange(e) {
       const selected = this._subsectionLinks
@@ -145,7 +155,7 @@
         return;
       }
       Gerrit.Nav.navigateToRelativeUrl(selected.url);
-    },
+    }
 
     _paramsChanged(params) {
       const isGroupView = params.view === Gerrit.Nav.View.GROUP;
@@ -194,19 +204,19 @@
       }
       if (!needsReload) { return; }
       this.reload();
-    },
+    }
 
     // TODO (beckysiegel): Update these functions after router abstraction is
     // updated. They are currently copied from gr-dropdown (and should be
     // updated there as well once complete).
     _computeURLHelper(host, path) {
       return '//' + host + this.getBaseUrl() + path;
-    },
+    }
 
     _computeRelativeURL(path) {
       const host = window.location.host;
       return this._computeURLHelper(host, path);
-    },
+    }
 
     _computeLinkURL(link) {
       if (!link || typeof link.url === 'undefined') { return ''; }
@@ -214,7 +224,7 @@
         return link.url;
       }
       return this._computeRelativeURL(link.url);
-    },
+    }
 
     /**
      * @param {string} itemView
@@ -244,7 +254,7 @@
         return '';
       }
       return itemView === params.adminView ? 'selected' : '';
-    },
+    }
 
     _computeGroupName(groupId) {
       if (!groupId) { return ''; }
@@ -270,11 +280,13 @@
           this.reload();
         });
       });
-    },
+    }
 
     _updateGroupName(e) {
       this._groupName = e.detail.name;
       this.reload();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAdminView.is, GrAdminView);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html
index 984be19..e6eef75 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-admin-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.js b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.js
index acc76de..e257c71 100644
--- a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.js
@@ -23,9 +23,15 @@
     TAGS: 'tags',
   };
 
-  Polymer({
-    is: 'gr-confirm-delete-item-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmDeleteItemDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-delete-item-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -38,26 +44,24 @@
      * @event cancel
      */
 
-    properties: {
-      item: String,
-      itemType: String,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        item: String,
+        itemType: String,
+      };
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
+    }
 
     _computeItemName(detailType) {
       if (detailType === DETAIL_TYPES.BRANCHES) {
@@ -67,6 +71,9 @@
       } else if (detailType === DETAIL_TYPES.ID) {
         return 'ID';
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmDeleteItemDialog.is,
+      GrConfirmDeleteItemDialog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html
index 3292cec..c83349b 100644
--- a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-delete-item-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
index 2a95991..1d6e706 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.html
@@ -31,7 +31,9 @@
 
 <dom-module id="gr-create-change-dialog">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       input:not([type="checkbox"]),
       gr-autocomplete,
@@ -41,11 +43,6 @@
       .value {
         width: 32em;
       }
-      gr-autocomplete {
-        --gr-autocomplete: {
-          padding: 0 var(--spacing-xs);
-        }
-      }
       .hide {
         display: none;
       }
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
index e29e5f8..31e2793 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.js
@@ -20,44 +20,52 @@
   const SUGGESTIONS_LIMIT = 15;
   const REF_PREFIX = 'refs/heads/';
 
-  Polymer({
-    is: 'gr-create-change-dialog',
-
-    properties: {
-      repoName: String,
-      branch: String,
-      /** @type {?} */
-      _repoConfig: Object,
-      subject: String,
-      topic: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getRepoBranchesSuggestions.bind(this);
-        },
-      },
-      baseChange: String,
-      baseCommit: String,
-      privateByDefault: String,
-      canCreate: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
-      _privateChangesEnabled: Boolean,
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      /**
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrCreateChangeDialog extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    /**
        * Unused in this element, but called by other elements in tests
        * e.g gr-repo-commands_test.
        */
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-create-change-dialog'; }
+
+    static get properties() {
+      return {
+        repoName: String,
+        branch: String,
+        /** @type {?} */
+        _repoConfig: Object,
+        subject: String,
+        topic: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getRepoBranchesSuggestions.bind(this);
+          },
+        },
+        baseChange: String,
+        baseCommit: String,
+        privateByDefault: String,
+        canCreate: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
+        _privateChangesEnabled: Boolean,
+      };
+    }
 
     attached() {
+      super.attached();
       if (!this.repoName) { return Promise.resolve(); }
 
       const promises = [];
@@ -75,19 +83,21 @@
       }));
 
       return Promise.all(promises);
-    },
+    }
 
-    observers: [
-      '_allowCreate(branch, subject)',
-    ],
+    static get observers() {
+      return [
+        '_allowCreate(branch, subject)',
+      ];
+    }
 
     _computeBranchClass(baseChange) {
       return baseChange ? 'hide' : '';
-    },
+    }
 
     _allowCreate(branch, subject) {
       this.canCreate = !!branch && !!subject;
-    },
+    }
 
     handleCreateChange() {
       const isPrivate = this.$.privateChangeCheckBox.checked;
@@ -99,7 +109,7 @@
             if (!changeCreated) { return; }
             Gerrit.Nav.navigateToChange(changeCreated);
           });
-    },
+    }
 
     _getRepoBranchesSuggestions(input) {
       if (input.startsWith(REF_PREFIX)) {
@@ -122,7 +132,7 @@
         }
         return branches;
       });
-    },
+    }
 
     _formatBooleanString(config) {
       if (config && config.configured_value === 'TRUE') {
@@ -138,10 +148,12 @@
       } else {
         return false;
       }
-    },
+    }
 
     _computePrivateSectionClass(config) {
       return config ? 'hide' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateChangeDialog.is, GrCreateChangeDialog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
index 3a3683f..3367aa3 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-change-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.html b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.html
index 8a4287b..d0a1fca 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.html
@@ -26,7 +26,9 @@
 
 <dom-module id="gr-create-group-dialog">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       :host {
         display: inline-block;
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.js b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.js
index 01aeb43..6b1af9a 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.js
@@ -17,40 +17,48 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-create-group-dialog',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrCreateGroupDialog extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-create-group-dialog'; }
 
-    properties: {
-      params: Object,
-      hasNewGroupName: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
-      _name: Object,
-      _groupCreated: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        params: Object,
+        hasNewGroupName: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
+        _name: Object,
+        _groupCreated: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    observers: [
-      '_updateGroupName(_name)',
-    ],
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    static get observers() {
+      return [
+        '_updateGroupName(_name)',
+      ];
+    }
 
     _computeGroupUrl(groupId) {
       return this.getBaseUrl() + '/admin/groups/' +
           this.encodeURL(groupId, true);
-    },
+    }
 
     _updateGroupName(name) {
       this.hasNewGroupName = !!name;
-    },
+    }
 
     handleCreateGroup() {
       return this.$.restAPI.createGroup({name: this._name})
@@ -62,6 +70,8 @@
                   page.show(this._computeGroupUrl(group.group_id));
                 });
           });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateGroupDialog.is, GrCreateGroupDialog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html
index ebca289..3a99526 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-group-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
@@ -56,7 +56,8 @@
     test('name is updated correctly', done => {
       assert.isFalse(element.hasNewGroupName);
 
-      ironInput(element.root).bindValue = GROUP_NAME;
+      const inputEl = element.root.querySelector('iron-input');
+      inputEl.bindValue = GROUP_NAME;
 
       setTimeout(() => {
         assert.isTrue(element.hasNewGroupName);
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.html b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.html
index ea5b84b..5a9213b 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.html
@@ -28,7 +28,9 @@
 
 <dom-module id="gr-create-pointer-dialog">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       :host {
         display: inline-block;
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.js b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.js
index 4e9da90..56d7bc8 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.js
@@ -22,35 +22,43 @@
     tags: 'tags',
   };
 
-  Polymer({
-    is: 'gr-create-pointer-dialog',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrCreatePointerDialog extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-create-pointer-dialog'; }
 
-    properties: {
-      detailType: String,
-      repoName: String,
-      hasNewItemName: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
-      itemDetail: String,
-      _itemName: String,
-      _itemRevision: String,
-      _itemAnnotation: String,
-    },
+    static get properties() {
+      return {
+        detailType: String,
+        repoName: String,
+        hasNewItemName: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
+        itemDetail: String,
+        _itemName: String,
+        _itemRevision: String,
+        _itemAnnotation: String,
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    observers: [
-      '_updateItemName(_itemName)',
-    ],
+    static get observers() {
+      return [
+        '_updateItemName(_itemName)',
+      ];
+    }
 
     _updateItemName(name) {
       this.hasNewItemName = !!name;
-    },
+    }
 
     _computeItemUrl(project) {
       if (this.itemDetail === DETAIL_TYPES.branches) {
@@ -60,7 +68,7 @@
         return this.getBaseUrl() + '/admin/repos/' +
             this.encodeURL(this.repoName, true) + ',tags';
       }
-    },
+    }
 
     handleCreateItem() {
       const USE_HEAD = this._itemRevision ? this._itemRevision : 'HEAD';
@@ -82,10 +90,12 @@
               }
             });
       }
-    },
+    }
 
     _computeHideItemClass(type) {
       return type === DETAIL_TYPES.branches ? 'hideItem' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreatePointerDialog.is, GrCreatePointerDialog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html
index 08e8213..41b8eca 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-pointer-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -39,6 +39,10 @@
     let element;
     let sandbox;
 
+    const ironInput = function(element) {
+      return Polymer.dom(element).querySelector('iron-input');
+    };
+
     setup(() => {
       sandbox = sinon.sandbox.create();
       stub('gr-rest-api-interface', {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.html b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.html
index d1a2471..b78090c 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.html
@@ -29,7 +29,9 @@
 
 <dom-module id="gr-create-repo-dialog">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       :host {
         display: inline-block;
@@ -38,14 +40,7 @@
         width: 20em;
       }
       gr-autocomplete {
-        border: none;
-        --gr-autocomplete: {
-          border: 1px solid var(--border-color);
-          border-radius: var(--border-radius);
-          height: 2em;
-          padding: 0 var(--spacing-xs);
-          width: 20em;
-        }
+        width: 20em;
       }
     </style>
 
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.js b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.js
index bb2b5f2..fd6dc4a 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.js
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.js
@@ -17,69 +17,77 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-create-repo-dialog',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrCreateRepoDialog extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-create-repo-dialog'; }
 
-    properties: {
-      params: Object,
-      hasNewRepoName: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
+    static get properties() {
+      return {
+        params: Object,
+        hasNewRepoName: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
 
-      /** @type {?} */
-      _repoConfig: {
-        type: Object,
-        value: () => {
+        /** @type {?} */
+        _repoConfig: {
+          type: Object,
+          value: () => {
           // Set default values for dropdowns.
-          return {
-            create_empty_commit: true,
-            permissions_only: false,
-          };
+            return {
+              create_empty_commit: true,
+              permissions_only: false,
+            };
+          },
         },
-      },
-      _repoCreated: {
-        type: Boolean,
-        value: false,
-      },
-      _repoOwner: String,
-      _repoOwnerId: {
-        type: String,
-        observer: '_repoOwnerIdUpdate',
-      },
-
-      _query: {
-        type: Function,
-        value() {
-          return this._getRepoSuggestions.bind(this);
+        _repoCreated: {
+          type: Boolean,
+          value: false,
         },
-      },
-      _queryGroups: {
-        type: Function,
-        value() {
-          return this._getGroupSuggestions.bind(this);
+        _repoOwner: String,
+        _repoOwnerId: {
+          type: String,
+          observer: '_repoOwnerIdUpdate',
         },
-      },
-    },
 
-    observers: [
-      '_updateRepoName(_repoConfig.name)',
-    ],
+        _query: {
+          type: Function,
+          value() {
+            return this._getRepoSuggestions.bind(this);
+          },
+        },
+        _queryGroups: {
+          type: Function,
+          value() {
+            return this._getGroupSuggestions.bind(this);
+          },
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    static get observers() {
+      return [
+        '_updateRepoName(_repoConfig.name)',
+      ];
+    }
 
     _computeRepoUrl(repoName) {
       return this.getBaseUrl() + '/admin/repos/' +
           this.encodeURL(repoName, true);
-    },
+    }
 
     _updateRepoName(name) {
       this.hasNewRepoName = !!name;
-    },
+    }
 
     _repoOwnerIdUpdate(id) {
       if (id) {
@@ -87,7 +95,7 @@
       } else {
         this.set('_repoConfig.owners', undefined);
       }
-    },
+    }
 
     handleCreateRepo() {
       return this.$.restAPI.createRepo(this._repoConfig)
@@ -97,7 +105,7 @@
               page.show(this._computeRepoUrl(this._repoConfig.name));
             }
           });
-    },
+    }
 
     _getRepoSuggestions(input) {
       return this.$.restAPI.getSuggestedProjects(input)
@@ -112,7 +120,7 @@
             }
             return repos;
           });
-    },
+    }
 
     _getGroupSuggestions(input) {
       return this.$.restAPI.getSuggestedGroups(input)
@@ -127,6 +135,8 @@
             }
             return groups;
           });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateRepoDialog.is, GrCreateRepoDialog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html
index 7e32c5c..fa481c2 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-repo-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.html b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.html
index b2e8045..4ed751d 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.html
@@ -23,10 +23,13 @@
 <link rel="import" href="../../core/gr-navigation/gr-navigation.html">
 <link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+<link rel="import" href="../../shared/gr-account-link/gr-account-link.html">
 
 <dom-module id="gr-group-audit-log">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-table-styles">
       /* GenericList style centers the last column, but we don't want that here. */
       .genericList tr th:last-of-type,
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.js b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.js
index 8901d4a..e0c980c 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.js
+++ b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log.js
@@ -19,30 +19,38 @@
 
   const GROUP_EVENTS = ['ADD_GROUP', 'REMOVE_GROUP'];
 
-  Polymer({
-    is: 'gr-group-audit-log',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.ListViewMixin
+    */
+  class GrGroupAuditLog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.ListViewBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-group-audit-log'; }
 
-    properties: {
-      groupId: String,
-      _auditLog: Array,
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.ListViewBehavior,
-    ],
+    static get properties() {
+      return {
+        groupId: String,
+        _auditLog: Array,
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this.fire('title-change', {title: 'Audit Log'});
-    },
+    }
 
     ready() {
+      super.ready();
       this._getAuditLogs();
-    },
+    }
 
     _getAuditLogs() {
       if (!this.groupId) { return ''; }
@@ -60,11 +68,11 @@
             this._auditLog = auditLog;
             this._loading = false;
           });
-    },
+    }
 
     _status(item) {
       return item.disabled ? 'Disabled' : 'Enabled';
-    },
+    }
 
     itemType(type) {
       let item;
@@ -81,11 +89,11 @@
           item = '';
       }
       return item;
-    },
+    }
 
     _isGroupEvent(type) {
       return GROUP_EVENTS.indexOf(type) !== -1;
-    },
+    }
 
     _computeGroupUrl(group) {
       if (group && group.url && group.id) {
@@ -93,11 +101,11 @@
       }
 
       return '';
-    },
+    }
 
     _getIdForUser(account) {
       return account._account_id ? ' (' + account._account_id + ')' : '';
-    },
+    }
 
     _getNameForGroup(group) {
       if (group && group.name) {
@@ -108,6 +116,8 @@
       }
 
       return '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrGroupAuditLog.is, GrGroupAuditLog);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html
index 313d465..d517242 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-audit-log/gr-group-audit-log_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-group-audit-log</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
index 86f66c4..cf24793 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.html
@@ -33,19 +33,21 @@
 
 <dom-module id="gr-group-members">
   <template>
-    <style include="gr-form-styles"></style>
-    <style include="gr-table-styles"></style>
-    <style include="gr-subpage-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-subpage-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       .input {
         width: 15em;
       }
       gr-autocomplete {
         width: 20em;
-        --gr-autocomplete: {
-          height: 2em;
-          width: 20em;
-        }
       }
       a {
         color: var(--primary-text-color);
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
index 7f8e9ac..574bc29 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members.js
@@ -23,57 +23,65 @@
 
   const URL_REGEX = '^(?:[a-z]+:)?//';
 
-  Polymer({
-    is: 'gr-group-members',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrGroupMembers extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-group-members'; }
 
-    properties: {
-      groupId: Number,
-      _groupMemberSearchId: String,
-      _groupMemberSearchName: String,
-      _includedGroupSearchId: String,
-      _includedGroupSearchName: String,
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _groupName: String,
-      _groupMembers: Object,
-      _includedGroups: Object,
-      _itemName: String,
-      _itemType: String,
-      _queryMembers: {
-        type: Function,
-        value() {
-          return this._getAccountSuggestions.bind(this);
+    static get properties() {
+      return {
+        groupId: Number,
+        _groupMemberSearchId: String,
+        _groupMemberSearchName: String,
+        _includedGroupSearchId: String,
+        _includedGroupSearchName: String,
+        _loading: {
+          type: Boolean,
+          value: true,
         },
-      },
-      _queryIncludedGroup: {
-        type: Function,
-        value() {
-          return this._getGroupSuggestions.bind(this);
+        _groupName: String,
+        _groupMembers: Object,
+        _includedGroups: Object,
+        _itemName: String,
+        _itemType: String,
+        _queryMembers: {
+          type: Function,
+          value() {
+            return this._getAccountSuggestions.bind(this);
+          },
         },
-      },
-      _groupOwner: {
-        type: Boolean,
-        value: false,
-      },
-      _isAdmin: {
-        type: Boolean,
-        value: false,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+        _queryIncludedGroup: {
+          type: Function,
+          value() {
+            return this._getGroupSuggestions.bind(this);
+          },
+        },
+        _groupOwner: {
+          type: Boolean,
+          value: false,
+        },
+        _isAdmin: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this._loadGroupDetails();
 
       this.fire('title-change', {title: 'Members'});
-    },
+    }
 
     _loadGroupDetails() {
       if (!this.groupId) { return; }
@@ -113,15 +121,15 @@
               this._loading = false;
             });
           });
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _isLoading() {
       return this._loading || this._loading === undefined;
-    },
+    }
 
     _computeGroupUrl(url) {
       if (!url) { return; }
@@ -136,7 +144,7 @@
         return this.getBaseUrl() + url.slice(1);
       }
       return this.getBaseUrl() + url;
-    },
+    }
 
     _handleSavingGroupMember() {
       return this.$.restAPI.saveGroupMembers(this._groupName,
@@ -150,7 +158,7 @@
         this._groupMemberSearchName = '';
         this._groupMemberSearchId = '';
       });
-    },
+    }
 
     _handleDeleteConfirm() {
       this.$.overlay.close();
@@ -177,11 +185,11 @@
               }
             });
       }
-    },
+    }
 
     _handleConfirmDialogCancel() {
       this.$.overlay.close();
-    },
+    }
 
     _handleDeleteMember(e) {
       const id = e.model.get('item._account_id');
@@ -196,7 +204,7 @@
       this._itemId = id;
       this._itemType = 'member';
       this.$.overlay.open();
-    },
+    }
 
     _handleSavingIncludedGroups() {
       return this.$.restAPI.saveIncludedGroup(this._groupName,
@@ -222,7 +230,7 @@
             this._includedGroupSearchName = '';
             this._includedGroupSearchId = '';
           });
-    },
+    }
 
     _handleDeleteIncludedGroup(e) {
       const id = decodeURIComponent(e.model.get('item.id')).replace(/\+/g, ' ');
@@ -233,7 +241,7 @@
       this._itemId = id;
       this._itemType = 'includedGroup';
       this.$.overlay.open();
-    },
+    }
 
     _getAccountSuggestions(input) {
       if (input.length === 0) { return Promise.resolve([]); }
@@ -257,7 +265,7 @@
         }
         return accountSuggestions;
       });
-    },
+    }
 
     _getGroupSuggestions(input) {
       return this.$.restAPI.getSuggestedGroups(input)
@@ -272,10 +280,12 @@
             }
             return groups;
           });
-    },
+    }
 
     _computeHideItemClass(owner, admin) {
       return admin || owner ? '' : 'canModify';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrGroupMembers.is, GrGroupMembers);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
index bf9113b..e90e6fd 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-group-members</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.html b/polygerrit-ui/app/elements/admin/gr-group/gr-group.html
index 19879cb..faabe84 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.html
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.html
@@ -28,7 +28,9 @@
 
 <dom-module id="gr-group">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-subpage-styles">
       h3.edited:after {
         color: var(--deemphasized-text-color);
@@ -38,7 +40,9 @@
         margin-top: var(--spacing-s);
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <main class="gr-form-styles read-only">
       <div id="loading" class$="[[_computeLoadingClass(_loading)]]">
         Loading...
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group.js b/polygerrit-ui/app/elements/admin/gr-group/gr-group.js
index 19cb45c..760ab9fa 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group.js
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group.js
@@ -30,78 +30,85 @@
     },
   };
 
-  Polymer({
-    is: 'gr-group',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrGroup extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-group'; }
     /**
      * Fired when the group name changes.
      *
      * @event name-changed
      */
 
-    properties: {
-      groupId: Number,
-      _rename: {
-        type: Boolean,
-        value: false,
-      },
-      _groupIsInternal: Boolean,
-      _description: {
-        type: Boolean,
-        value: false,
-      },
-      _owner: {
-        type: Boolean,
-        value: false,
-      },
-      _options: {
-        type: Boolean,
-        value: false,
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      /** @type {?} */
-      _groupConfig: Object,
-      _groupConfigOwner: String,
-      _groupName: Object,
-      _groupOwner: {
-        type: Boolean,
-        value: false,
-      },
-      _submitTypes: {
-        type: Array,
-        value() {
-          return Object.values(OPTIONS);
+    static get properties() {
+      return {
+        groupId: Number,
+        _rename: {
+          type: Boolean,
+          value: false,
         },
-      },
-      _query: {
-        type: Function,
-        value() {
-          return this._getGroupSuggestions.bind(this);
+        _groupIsInternal: Boolean,
+        _description: {
+          type: Boolean,
+          value: false,
         },
-      },
-      _isAdmin: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _owner: {
+          type: Boolean,
+          value: false,
+        },
+        _options: {
+          type: Boolean,
+          value: false,
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        /** @type {?} */
+        _groupConfig: Object,
+        _groupConfigOwner: String,
+        _groupName: Object,
+        _groupOwner: {
+          type: Boolean,
+          value: false,
+        },
+        _submitTypes: {
+          type: Array,
+          value() {
+            return Object.values(OPTIONS);
+          },
+        },
+        _query: {
+          type: Function,
+          value() {
+            return this._getGroupSuggestions.bind(this);
+          },
+        },
+        _isAdmin: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_handleConfigName(_groupConfig.name)',
-      '_handleConfigOwner(_groupConfig.owner, _groupConfigOwner)',
-      '_handleConfigDescription(_groupConfig.description)',
-      '_handleConfigOptions(_groupConfig.options.visible_to_all)',
-    ],
+    static get observers() {
+      return [
+        '_handleConfigName(_groupConfig.name)',
+        '_handleConfigOwner(_groupConfig.owner, _groupConfigOwner)',
+        '_handleConfigDescription(_groupConfig.description)',
+        '_handleConfigOptions(_groupConfig.options.visible_to_all)',
+      ];
+    }
 
     attached() {
+      super.attached();
       this._loadGroup();
-    },
+    }
 
     _loadGroup() {
       if (!this.groupId) { return; }
@@ -143,15 +150,15 @@
               this._loading = false;
             });
           });
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _isLoading() {
       return this._loading || this._loading === undefined;
-    },
+    }
 
     _handleSaveName() {
       return this.$.restAPI.saveGroupName(this.groupId, this._groupConfig.name)
@@ -163,7 +170,7 @@
               this._rename = false;
             }
           });
-    },
+    }
 
     _handleSaveOwner() {
       let owner = this._groupConfig.owner;
@@ -174,14 +181,14 @@
           owner).then(config => {
         this._owner = false;
       });
-    },
+    }
 
     _handleSaveDescription() {
       return this.$.restAPI.saveGroupDescription(this.groupId,
           this._groupConfig.description).then(config => {
         this._description = false;
       });
-    },
+    }
 
     _handleSaveOptions() {
       const visible = this._groupConfig.options.visible_to_all;
@@ -192,31 +199,31 @@
           options).then(config => {
         this._options = false;
       });
-    },
+    }
 
     _handleConfigName() {
       if (this._isLoading()) { return; }
       this._rename = true;
-    },
+    }
 
     _handleConfigOwner() {
       if (this._isLoading()) { return; }
       this._owner = true;
-    },
+    }
 
     _handleConfigDescription() {
       if (this._isLoading()) { return; }
       this._description = true;
-    },
+    }
 
     _handleConfigOptions() {
       if (this._isLoading()) { return; }
       this._options = true;
-    },
+    }
 
     _computeHeaderClass(configChanged) {
       return configChanged ? 'edited' : '';
-    },
+    }
 
     _getGroupSuggestions(input) {
       return this.$.restAPI.getSuggestedGroups(input)
@@ -231,10 +238,12 @@
             }
             return groups;
           });
-    },
+    }
 
     _computeGroupDisabled(owner, admin, groupIsInternal) {
       return groupIsInternal && (admin || owner) ? false : true;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrGroup.is, GrGroup);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html b/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html
index 1672e85..0d7aae2 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-group</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
index 931e2cd..e07f911 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.html
@@ -82,8 +82,12 @@
         display: block;
       }
     </style>
-    <style include="gr-form-styles"></style>
-    <style include="gr-menu-page-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-menu-page-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <section
         id="permission"
         class$="gr-form-styles [[_computeSectionClass(editing, _deleted)]]">
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
index c485b15..e1e7c0a 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
@@ -25,91 +25,100 @@
   ];
 
   /**
+    * @appliesMixin Gerrit.AccessMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  /**
    * Fired when the permission has been modified or removed.
    *
    * @event access-modified
    */
-
   /**
    * Fired when a permission that was previously added was removed.
    * @event added-permission-removed
    */
-
-  Polymer({
-    is: 'gr-permission',
-
-    properties: {
-      labels: Object,
-      name: String,
-      /** @type {?} */
-      permission: {
-        type: Object,
-        observer: '_sortPermission',
-        notify: true,
-      },
-      groups: Object,
-      section: String,
-      editing: {
-        type: Boolean,
-        value: false,
-        observer: '_handleEditingChanged',
-      },
-      _label: {
-        type: Object,
-        computed: '_computeLabel(permission, labels)',
-      },
-      _groupFilter: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getGroupSuggestions.bind(this);
-        },
-      },
-      _rules: Array,
-      _groupsWithRules: Object,
-      _deleted: {
-        type: Boolean,
-        value: false,
-      },
-      _originalExclusiveValue: Boolean,
-    },
-
-    behaviors: [
-      Gerrit.AccessBehavior,
-      /**
+  class GrPermission extends Polymer.mixinBehaviors( [
+    Gerrit.AccessBehavior,
+    /**
        * Unused in this element, but called by other elements in tests
        * e.g gr-access-section_test.
        */
-      Gerrit.FireBehavior,
-    ],
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-permission'; }
 
-    observers: [
-      '_handleRulesChanged(_rules.splices)',
-    ],
+    static get properties() {
+      return {
+        labels: Object,
+        name: String,
+        /** @type {?} */
+        permission: {
+          type: Object,
+          observer: '_sortPermission',
+          notify: true,
+        },
+        groups: Object,
+        section: String,
+        editing: {
+          type: Boolean,
+          value: false,
+          observer: '_handleEditingChanged',
+        },
+        _label: {
+          type: Object,
+          computed: '_computeLabel(permission, labels)',
+        },
+        _groupFilter: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getGroupSuggestions.bind(this);
+          },
+        },
+        _rules: Array,
+        _groupsWithRules: Object,
+        _deleted: {
+          type: Boolean,
+          value: false,
+        },
+        _originalExclusiveValue: Boolean,
+      };
+    }
 
-    listeners: {
-      'access-saved': '_handleAccessSaved',
-    },
+    static get observers() {
+      return [
+        '_handleRulesChanged(_rules.splices)',
+      ];
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('access-saved',
+          () => this._handleAccessSaved());
+    }
 
     ready() {
+      super.ready();
       this._setupValues();
-    },
+    }
 
     _setupValues() {
       if (!this.permission) { return; }
       this._originalExclusiveValue = !!this.permission.value.exclusive;
       Polymer.dom.flush();
-    },
+    }
 
     _handleAccessSaved() {
       // Set a new 'original' value to keep track of after the value has been
       // saved.
       this._setupValues();
-    },
+    }
 
     _permissionIsOwnerOrGlobal(permissionId, section) {
       return permissionId === 'owner' || section === 'GLOBAL_CAPABILITIES';
-    },
+    }
 
     _handleEditingChanged(editing, editingOld) {
       // Ignore when editing gets set initially.
@@ -130,20 +139,20 @@
         this.set(['permission', 'value', 'exclusive'],
             this._originalExclusiveValue);
       }
-    },
+    }
 
     _handleAddedRuleRemoved(e) {
       const index = e.model.index;
       this._rules = this._rules.slice(0, index)
           .concat(this._rules.slice(index + 1, this._rules.length));
-    },
+    }
 
     _handleValueChange() {
       this.permission.value.modified = true;
       // Allows overall access page to know a change has been made.
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _handleRemovePermission() {
       if (this.permission.value.added) {
@@ -154,16 +163,16 @@
       this.permission.value.deleted = true;
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _handleRulesChanged(changeRecord) {
       // Update the groups to exclude in the autocomplete.
       this._groupsWithRules = this._computeGroupsWithRules(this._rules);
-    },
+    }
 
     _sortPermission(permission) {
       this._rules = this.toSortedArray(permission.value.rules);
-    },
+    }
 
     _computeSectionClass(editing, deleted) {
       const classList = [];
@@ -174,12 +183,12 @@
         classList.push('deleted');
       }
       return classList.join(' ');
-    },
+    }
 
     _handleUndoRemove() {
       this._deleted = false;
       delete this.permission.value.deleted;
-    },
+    }
 
     _computeLabel(permission, labels) {
       if (!labels || !permission ||
@@ -195,7 +204,7 @@
         values: this._computeLabelValues(labels[labelName].values),
       };
       return label;
-    },
+    }
 
     _computeLabelValues(values) {
       const valuesArr = [];
@@ -211,7 +220,7 @@
         valuesArr.push({value: parseInt(key, 10), text});
       }
       return valuesArr;
-    },
+    }
 
     /**
      * @param {!Array} rules
@@ -224,12 +233,12 @@
         groups[rule.id] = true;
       }
       return groups;
-    },
+    }
 
     _computeGroupName(groups, groupId) {
       return groups && groups[groupId] && groups[groupId].name ?
         groups[groupId].name : groupId;
-    },
+    }
 
     _getGroupSuggestions() {
       return this.$.restAPI.getSuggestedGroups(
@@ -249,7 +258,7 @@
               return !this._groupsWithRules[group.value.id];
             });
           });
-    },
+    }
 
     /**
      * Handles adding a skeleton item to the dom-repeat.
@@ -283,12 +292,14 @@
       this.set(['permission', 'value', 'rules', groupId], value);
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _computeHasRange(name) {
       if (!name) { return false; }
 
       return RANGE_NAMES.includes(name.toUpperCase());
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPermission.is, GrPermission);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
index 8e57534..6cb7e4a 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-permission</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.html b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.html
index 5afd5b6..f6c744b 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.html
@@ -25,7 +25,9 @@
 
 <dom-module id="gr-plugin-config-array-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       .wrapper {
         width: 30em;
@@ -73,7 +75,7 @@
               <gr-button
                   link
                   disabled$="[[disabled]]"
-                  data-item="[[item]]"
+                  data-item$="[[item]]"
                   on-click="_handleDelete">Delete</gr-button>
             </div>
           </template>
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.js b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.js
index ab4d286..854bbbc 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.js
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor.js
@@ -17,39 +17,42 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-plugin-config-array-editor',
-
+  class GrPluginConfigArrayEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-plugin-config-array-editor'; }
     /**
      * Fired when the plugin config option changes.
      *
      * @event plugin-config-option-changed
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      pluginOption: Object,
-      /** @type {Boolean} */
-      disabled: {
-        type: Boolean,
-        computed: '_computeDisabled(pluginOption.*)',
-      },
-      /** @type {?} */
-      _newValue: {
-        type: String,
-        value: '',
-      },
-    },
+        pluginOption: Object,
+        /** @type {Boolean} */
+        disabled: {
+          type: Boolean,
+          computed: '_computeDisabled(pluginOption.*)',
+        },
+        /** @type {?} */
+        _newValue: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     _computeDisabled(record) {
       return !(record && record.base && record.base.info &&
           record.base.info.editable);
-    },
+    }
 
     _handleAddTap(e) {
       e.preventDefault();
       this._handleAdd();
-    },
+    }
 
     _handleInputKeydown(e) {
       // Enter.
@@ -57,20 +60,20 @@
         e.preventDefault();
         this._handleAdd();
       }
-    },
+    }
 
     _handleAdd() {
       if (!this._newValue.length) { return; }
       this._dispatchChanged(
           this.pluginOption.info.values.concat([this._newValue]));
       this._newValue = '';
-    },
+    }
 
     _handleDelete(e) {
-      const value = Polymer.dom(e).localTarget.dataItem;
+      const value = Polymer.dom(e).localTarget.dataset.item;
       this._dispatchChanged(
           this.pluginOption.info.values.filter(str => str !== value));
-    },
+    }
 
     _dispatchChanged(values) {
       const {_key, info} = this.pluginOption;
@@ -81,10 +84,13 @@
       };
       this.dispatchEvent(
           new CustomEvent('plugin-config-option-changed', {detail}));
-    },
+    }
 
     _computeShowInputRow(disabled) {
       return disabled ? 'hide' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPluginConfigArrayEditor.is,
+      GrPluginConfigArrayEditor);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html
index 39e4ddc..5198ad0 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-config-array-editor/gr-plugin-config-array-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-config-array-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.html b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.html
index 6ef84bf..b056f92 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.html
@@ -25,8 +25,12 @@
 
 <dom-module id="gr-plugin-list">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-table-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <gr-list-view
         filter="[[_filter]]"
         items-per-page="[[_pluginsPerPage]]"
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.js b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.js
index 1dbfdc8..e0089dc 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list.js
@@ -17,60 +17,67 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-plugin-list',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.ListViewMixin
+    */
+  class GrPluginList extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.ListViewBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-plugin-list'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
-      /**
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
+        /**
        * Offset of currently visible query results.
        */
-      _offset: {
-        type: Number,
-        value: 0,
-      },
-      _path: {
-        type: String,
-        readOnly: true,
-        value: '/admin/plugins',
-      },
-      _plugins: Array,
-      /**
+        _offset: {
+          type: Number,
+          value: 0,
+        },
+        _path: {
+          type: String,
+          readOnly: true,
+          value: '/admin/plugins',
+        },
+        _plugins: Array,
+        /**
        * Because  we request one more than the pluginsPerPage, _shownPlugins
        * maybe one less than _plugins.
        * */
-      _shownPlugins: {
-        type: Array,
-        computed: 'computeShownItems(_plugins)',
-      },
-      _pluginsPerPage: {
-        type: Number,
-        value: 25,
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _filter: {
-        type: String,
-        value: '',
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.ListViewBehavior,
-    ],
+        _shownPlugins: {
+          type: Array,
+          computed: 'computeShownItems(_plugins)',
+        },
+        _pluginsPerPage: {
+          type: Number,
+          value: 25,
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _filter: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this.fire('title-change', {title: 'Plugins'});
-    },
+    }
 
     _paramsChanged(params) {
       this._loading = true;
@@ -79,7 +86,7 @@
 
       return this._getPlugins(this._filter, this._pluginsPerPage,
           this._offset);
-    },
+    }
 
     _getPlugins(filter, pluginsPerPage, offset) {
       const errFn = response => {
@@ -99,14 +106,16 @@
                 });
             this._loading = false;
           });
-    },
+    }
 
     _status(item) {
       return item.disabled === true ? 'Disabled' : 'Enabled';
-    },
+    }
 
     _computePluginUrl(id) {
       return this.getUrl('/', id);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPluginList.is, GrPluginList);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html
index 96fff60..98636a8 100644
--- a/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-plugin-list/gr-plugin-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.html b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.html
index ea12908..fab730d 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.html
@@ -33,7 +33,9 @@
 
 <dom-module id="gr-repo-access">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-subpage-styles">
       gr-button,
       #inheritsFrom,
@@ -68,7 +70,9 @@
         display: inline-block;
       }
     </style>
-    <style include="gr-menu-page-styles"></style>
+    <style include="gr-menu-page-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <main class$="[[_computeMainClass(_ownerOf, _canUpload, _editing)]]">
       <div id="loading" class$="[[_computeLoadingClass(_loading)]]">
         Loading...
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.js b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.js
index fc50677..57a9183 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access.js
@@ -67,66 +67,77 @@
    */
   Defs.projectAccessInput;
 
-  Polymer({
-    is: 'gr-repo-access',
+  /**
+    * @appliesMixin Gerrit.AccessMixin
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrRepoAccess extends Polymer.mixinBehaviors( [
+    Gerrit.AccessBehavior,
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-access'; }
 
-    properties: {
-      repo: {
-        type: String,
-        observer: '_repoChanged',
-      },
-      // The current path
-      path: String,
-
-      _canUpload: {
-        type: Boolean,
-        value: false,
-      },
-      _inheritFromFilter: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getInheritFromSuggestions.bind(this);
+    static get properties() {
+      return {
+        repo: {
+          type: String,
+          observer: '_repoChanged',
         },
-      },
-      _ownerOf: Array,
-      _capabilities: Object,
-      _groups: Object,
-      /** @type {?} */
-      _inheritsFrom: Object,
-      _labels: Object,
-      _local: Object,
-      _editing: {
-        type: Boolean,
-        value: false,
-        observer: '_handleEditingChanged',
-      },
-      _modified: {
-        type: Boolean,
-        value: false,
-      },
-      _sections: Array,
-      _weblinks: Array,
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-    },
+        // The current path
+        path: String,
 
-    behaviors: [
-      Gerrit.AccessBehavior,
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+        _canUpload: {
+          type: Boolean,
+          value: false,
+        },
+        _inheritFromFilter: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getInheritFromSuggestions.bind(this);
+          },
+        },
+        _ownerOf: Array,
+        _capabilities: Object,
+        _groups: Object,
+        /** @type {?} */
+        _inheritsFrom: Object,
+        _labels: Object,
+        _local: Object,
+        _editing: {
+          type: Boolean,
+          value: false,
+          observer: '_handleEditingChanged',
+        },
+        _modified: {
+          type: Boolean,
+          value: false,
+        },
+        _sections: Array,
+        _weblinks: Array,
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+      };
+    }
 
-    listeners: {
-      'access-modified': '_handleAccessModified',
-    },
+    created() {
+      super.created();
+      this.addEventListener('access-modified',
+          () =>
+            this._handleAccessModified());
+    }
 
     _handleAccessModified() {
       this._modified = true;
-    },
+    }
 
     /**
      * @param {string} repo
@@ -138,7 +149,7 @@
       if (!repo) { return Promise.resolve(); }
 
       return this._reload(repo);
-    },
+    }
 
     _reload(repo) {
       const promises = [];
@@ -195,7 +206,7 @@
         this._sections = sections;
         this._loading = false;
       });
-    },
+    }
 
     _handleUpdateInheritFrom(e) {
       if (!this._inheritsFrom) {
@@ -204,7 +215,7 @@
       this._inheritsFrom.id = e.detail.value;
       this._inheritsFrom.name = this._inheritFromFilter;
       this._handleAccessModified();
-    },
+    }
 
     _getInheritFromSuggestions() {
       return this.$.restAPI.getRepos(
@@ -221,33 +232,33 @@
             }
             return projects;
           });
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _handleEdit() {
       this._editing = !this._editing;
-    },
+    }
 
     _editOrCancel(editing) {
       return editing ? 'Cancel' : 'Edit';
-    },
+    }
 
     _computeWebLinkClass(weblinks) {
       return weblinks && weblinks.length ? 'show' : '';
-    },
+    }
 
     _computeShowInherit(inheritsFrom) {
       return inheritsFrom ? 'show' : '';
-    },
+    }
 
     _handleAddedSectionRemoved(e) {
       const index = e.model.index;
       this._sections = this._sections.slice(0, index)
           .concat(this._sections.slice(index + 1, this._sections.length));
-    },
+    }
 
     _handleEditingChanged(editing, editingOld) {
       // Ignore when editing gets set initially.
@@ -266,7 +277,7 @@
           delete this._local[key];
         }
       }
-    },
+    }
 
     /**
      * @param {!Defs.projectAccessInput} addRemoveObj
@@ -296,7 +307,7 @@
         curPos = curPos[item];
       }
       return addRemoveObj;
-    },
+    }
 
     /**
      * Used to recursively remove any objects with a 'deleted' bit.
@@ -313,7 +324,7 @@
           this._recursivelyRemoveDeleted(obj[k]);
         }
       }
-    },
+    }
 
     _recursivelyUpdateAddRemoveObj(obj, addRemoveObj, path = []) {
       for (const k in obj) {
@@ -354,7 +365,7 @@
               path.concat(k));
         }
       }
-    },
+    }
 
     /**
      * Returns an object formatted for saving or submitting access changes for
@@ -388,7 +399,7 @@
         addRemoveObj.parent = inheritsFromId;
       }
       return addRemoveObj;
-    },
+    }
 
     _handleCreateSection() {
       let newRef = 'refs/for/*';
@@ -403,7 +414,7 @@
       Polymer.dom.flush();
       Polymer.dom(this.root).querySelector('gr-access-section:last-of-type')
           .editReference();
-    },
+    }
 
     _getObjforSave() {
       const addRemoveObj = this._computeAddAndRemove();
@@ -426,7 +437,7 @@
         obj.parent = addRemoveObj.parent;
       }
       return obj;
-    },
+    }
 
     _handleSave() {
       const obj = this._getObjforSave();
@@ -435,7 +446,7 @@
           .then(() => {
             this._reload(this.repo);
           });
-    },
+    }
 
     _handleSaveForReview() {
       const obj = this._getObjforSave();
@@ -444,15 +455,15 @@
           .then(change => {
             Gerrit.Nav.navigateToChange(change);
           });
-    },
+    }
 
     _computeSaveReviewBtnClass(canUpload) {
       return !canUpload ? 'invisible' : '';
-    },
+    }
 
     _computeSaveBtnClass(ownerOf) {
       return ownerOf && ownerOf.length === 0 ? 'invisible' : '';
-    },
+    }
 
     _computeMainClass(ownerOf, canUpload, editing) {
       const classList = [];
@@ -463,11 +474,13 @@
         classList.push('editing');
       }
       return classList.join(' ');
-    },
+    }
 
     _computeParentHref(repoName) {
       return this.getBaseUrl() +
           `/admin/repos/${this.encodeURL(repoName, true)},access`;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoAccess.is, GrRepoAccess);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html
index 1660088..90eaba5 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-access</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command.js b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command.js
index 026c990..48e4c01 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command.js
@@ -17,14 +17,18 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-command',
+  class GrRepoCommand extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-repo-command'; }
 
-    properties: {
-      title: String,
-      disabled: Boolean,
-      tooltip: String,
-    },
+    static get properties() {
+      return {
+        title: String,
+        disabled: Boolean,
+        tooltip: String,
+      };
+    }
 
     /**
      * Fired when command button is tapped.
@@ -35,6 +39,8 @@
     _onCommandTap() {
       this.dispatchEvent(
           new CustomEvent('command-tap', {bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoCommand.is, GrRepoCommand);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_test.html b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_test.html
index 49d8765..b8ec7e8 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-command</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.html b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.html
index 5089f34..b610460 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.html
@@ -31,9 +31,15 @@
 
 <dom-module id="gr-repo-commands">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-subpage-styles"></style>
-    <style include="gr-form-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-subpage-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <main class="gr-form-styles read-only">
       <h1 id="Title">Repository Commands</h1>
       <div id="loading" class$="[[_computeLoadingClass(_loading)]]">Loading...</div>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.js b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.js
index 95faaf8..f85af35 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands.js
@@ -26,30 +26,36 @@
   const CREATE_CHANGE_FAILED_MESSAGE = 'Failed to create change.';
   const CREATE_CHANGE_SUCCEEDED_MESSAGE = 'Navigating to change';
 
-  Polymer({
-    is: 'gr-repo-commands',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrRepoCommands extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-commands'; }
 
-    properties: {
-      params: Object,
-      repo: String,
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      /** @type {?} */
-      _repoConfig: Object,
-      _canCreate: Boolean,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        params: Object,
+        repo: String,
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        /** @type {?} */
+        _repoConfig: Object,
+        _canCreate: Boolean,
+      };
+    }
 
     attached() {
+      super.attached();
       this._loadRepo();
 
       this.fire('title-change', {title: 'Repo Commands'});
-    },
+    }
 
     _loadRepo() {
       if (!this.repo) { return Promise.resolve(); }
@@ -65,15 +71,15 @@
             this._repoConfig = config;
             this._loading = false;
           });
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _isLoading() {
       return this._loading || this._loading === undefined;
-    },
+    }
 
     _handleRunningGC() {
       return this.$.restAPI.runRepoGC(this.repo).then(response => {
@@ -83,20 +89,20 @@
               {detail: {message: GC_MESSAGE}, bubbles: true, composed: true}));
         }
       });
-    },
+    }
 
     _createNewChange() {
       this.$.createChangeOverlay.open();
-    },
+    }
 
     _handleCreateChange() {
       this.$.createNewChangeModal.handleCreateChange();
       this._handleCloseCreateChange();
-    },
+    }
 
     _handleCloseCreateChange() {
       this.$.createChangeOverlay.close();
-    },
+    }
 
     _handleEditRepoConfig() {
       return this.$.restAPI.createChange(this.repo, CONFIG_BRANCH,
@@ -112,6 +118,8 @@
         Gerrit.Nav.navigateToRelativeUrl(Gerrit.Nav.getEditUrlForDiff(
             change, CONFIG_PATH, INITIAL_PATCHSET));
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoCommands.is, GrRepoCommands);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html
index 2976923..3c19175 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-commands</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.html b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.html
index 8af3a92..f74f705 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.html
@@ -35,7 +35,9 @@
         display: block;
       }
     </style>
-    <style include="gr-table-styles"></style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <table id="list" class$="genericList [[_computeLoadingClass(_loading)]]">
       <tr class="headerRow">
         <th class="topHeader">Dashboard name</th>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.js b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.js
index 71cc571..b4d34ae 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards.js
@@ -17,24 +17,29 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-dashboards',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrRepoDashboards extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-dashboards'; }
 
-    properties: {
-      repo: {
-        type: String,
-        observer: '_repoChanged',
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _dashboards: Array,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        repo: {
+          type: String,
+          observer: '_repoChanged',
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _dashboards: Array,
+      };
+    }
 
     _repoChanged(repo) {
       this._loading = true;
@@ -70,24 +75,26 @@
         this._loading = false;
         Polymer.dom.flush();
       });
-    },
+    }
 
     _getUrl(project, id) {
       if (!project || !id) { return ''; }
 
       return Gerrit.Nav.getUrlForRepoDashboard(project, id);
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _computeInheritedFrom(project, definingProject) {
       return project === definingProject ? '' : definingProject;
-    },
+    }
 
     _computeIsDefault(isDefault) {
       return isDefault ? '✓' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoDashboards.is, GrRepoDashboards);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html
index 4f76983..06496de 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-dashboards/gr-repo-dashboards_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-dashboards</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.html b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.html
index 2f244f8..467cef0 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.html
@@ -35,8 +35,12 @@
 
 <dom-module id="gr-repo-detail-list">
   <template>
-    <style include="gr-form-styles"></style>
-    <style include="gr-table-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       .tags td.name {
         min-width: 25em;
@@ -81,7 +85,9 @@
         display: none;
       }
     </style>
-    <style include="gr-table-styles"></style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <gr-list-view
         create-new="[[_loggedIn]]"
         filter="[[_filter]]"
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.js b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.js
index 9052322..bacc1e1 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list.js
@@ -24,75 +24,82 @@
 
   const PGP_START = '-----BEGIN PGP SIGNATURE-----';
 
-  Polymer({
-    is: 'gr-repo-detail-list',
+  /**
+    * @appliesMixin Gerrit.ListViewMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrRepoDetailList extends Polymer.mixinBehaviors( [
+    Gerrit.ListViewBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-detail-list'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
-      /**
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
+        /**
        * The kind of detail we are displaying, possibilities are determined by
        * the const DETAIL_TYPES.
        */
-      detailType: String,
+        detailType: String,
 
-      _editing: {
-        type: Boolean,
-        value: false,
-      },
-      _isOwner: {
-        type: Boolean,
-        value: false,
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-      /**
+        _editing: {
+          type: Boolean,
+          value: false,
+        },
+        _isOwner: {
+          type: Boolean,
+          value: false,
+        },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+        /**
        * Offset of currently visible query results.
        */
-      _offset: Number,
-      _repo: Object,
-      _items: Array,
-      /**
+        _offset: Number,
+        _repo: Object,
+        _items: Array,
+        /**
        * Because  we request one more than the projectsPerPage, _shownProjects
        * maybe one less than _projects.
        */
-      _shownItems: {
-        type: Array,
-        computed: 'computeShownItems(_items)',
-      },
-      _itemsPerPage: {
-        type: Number,
-        value: 25,
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _filter: String,
-      _refName: String,
-      _hasNewItemName: Boolean,
-      _isEditing: Boolean,
-      _revisedRef: String,
-    },
-
-    behaviors: [
-      Gerrit.ListViewBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+        _shownItems: {
+          type: Array,
+          computed: 'computeShownItems(_items)',
+        },
+        _itemsPerPage: {
+          type: Number,
+          value: 25,
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _filter: String,
+        _refName: String,
+        _hasNewItemName: Boolean,
+        _isEditing: Boolean,
+        _revisedRef: String,
+      };
+    }
 
     _determineIfOwner(repo) {
       return this.$.restAPI.getRepoAccess(repo)
           .then(access =>
             this._isOwner = access && !!access[repo].is_owner);
-    },
+    }
 
     _paramsChanged(params) {
       if (!params || !params.repo) { return; }
@@ -113,7 +120,7 @@
 
       return this._getItems(this._filter, this._repo,
           this._itemsPerPage, this._offset, this.detailType);
-    },
+    }
 
     _getItems(filter, repo, itemsPerPage, offset, detailType) {
       this._loading = true;
@@ -137,24 +144,24 @@
           this._loading = false;
         });
       }
-    },
+    }
 
     _getPath(repo) {
       return `/admin/repos/${this.encodeURL(repo, false)},` +
           `${this.detailType}`;
-    },
+    }
 
     _computeWeblink(repo) {
       if (!repo.web_links) { return ''; }
       const webLinks = repo.web_links;
       return webLinks.length ? webLinks : null;
-    },
+    }
 
     _computeMessage(message) {
       if (!message) { return; }
       // Strip PGP info.
       return message.split(PGP_START)[0];
-    },
+    }
 
     _stripRefs(item, detailType) {
       if (detailType === DETAIL_TYPES.BRANCHES) {
@@ -162,33 +169,33 @@
       } else if (detailType === DETAIL_TYPES.TAGS) {
         return item.replace('refs/tags/', '');
       }
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _computeEditingClass(isEditing) {
       return isEditing ? 'editing' : '';
-    },
+    }
 
     _computeCanEditClass(ref, detailType, isOwner) {
       return isOwner && this._stripRefs(ref, detailType) === 'HEAD' ?
         'canEdit' : '';
-    },
+    }
 
     _handleEditRevision(e) {
       this._revisedRef = e.model.get('item.revision');
       this._isEditing = true;
-    },
+    }
 
     _handleCancelRevision() {
       this._isEditing = false;
-    },
+    }
 
     _handleSaveRevision(e) {
       this._setRepoHead(this._repo, this._revisedRef, e);
-    },
+    }
 
     _setRepoHead(repo, ref, e) {
       return this.$.restAPI.setRepoHead(repo, ref).then(res => {
@@ -202,7 +209,7 @@
               this._offset, this.detailType);
         }
       });
-    },
+    }
 
     _computeItemName(detailType) {
       if (detailType === DETAIL_TYPES.BRANCHES) {
@@ -210,7 +217,7 @@
       } else if (detailType === DETAIL_TYPES.TAGS) {
         return 'Tag';
       }
-    },
+    }
 
     _handleDeleteItemConfirm() {
       this.$.overlay.close();
@@ -233,18 +240,18 @@
               }
             });
       }
-    },
+    }
 
     _handleConfirmDialogCancel() {
       this.$.overlay.close();
-    },
+    }
 
     _handleDeleteItem(e) {
       const name = this._stripRefs(e.model.get('item.ref'), this.detailType);
       if (!name) { return; }
       this._refName = name;
       this.$.overlay.open();
-    },
+    }
 
     _computeHideDeleteClass(owner, canDelete) {
       if (canDelete || owner) {
@@ -252,20 +259,20 @@
       }
 
       return '';
-    },
+    }
 
     _handleCreateItem() {
       this.$.createNewModal.handleCreateItem();
       this._handleCloseCreate();
-    },
+    }
 
     _handleCloseCreate() {
       this.$.createOverlay.close();
-    },
+    }
 
     _handleCreateClicked() {
       this.$.createOverlay.open();
-    },
+    }
 
     _hideIfBranch(type) {
       if (type === DETAIL_TYPES.BRANCHES) {
@@ -273,10 +280,12 @@
       }
 
       return '';
-    },
+    }
 
     _computeHideTagger(tagger) {
       return tagger ? '' : 'hide';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoDetailList.is, GrRepoDetailList);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html
index 44d9b27..2b175c7 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-detail-list/gr-repo-detail-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-detail-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.html b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.html
index 5e82c1e..08fd45c 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.html
@@ -27,8 +27,12 @@
 
 <dom-module id="gr-repo-list">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-table-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style>
       .genericList tr td:last-of-type {
         text-align: left;
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
index e0b054b..82bb3e2 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list.js
@@ -17,67 +17,73 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-list',
+  /**
+    * @appliesMixin Gerrit.ListViewMixin
+    */
+  class GrRepoList extends Polymer.mixinBehaviors( [
+    Gerrit.ListViewBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-list'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      /**
+        /**
        * Offset of currently visible query results.
        */
-      _offset: Number,
-      _path: {
-        type: String,
-        readOnly: true,
-        value: '/admin/repos',
-      },
-      _hasNewRepoName: Boolean,
-      _createNewCapability: {
-        type: Boolean,
-        value: false,
-      },
-      _repos: Array,
+        _offset: Number,
+        _path: {
+          type: String,
+          readOnly: true,
+          value: '/admin/repos',
+        },
+        _hasNewRepoName: Boolean,
+        _createNewCapability: {
+          type: Boolean,
+          value: false,
+        },
+        _repos: Array,
 
-      /**
+        /**
        * Because  we request one more than the projectsPerPage, _shownProjects
        * maybe one less than _projects.
        * */
-      _shownRepos: {
-        type: Array,
-        computed: 'computeShownItems(_repos)',
-      },
+        _shownRepos: {
+          type: Array,
+          computed: 'computeShownItems(_repos)',
+        },
 
-      _reposPerPage: {
-        type: Number,
-        value: 25,
-      },
+        _reposPerPage: {
+          type: Number,
+          value: 25,
+        },
 
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _filter: {
-        type: String,
-        value: '',
-      },
-    },
-
-    behaviors: [
-      Gerrit.ListViewBehavior,
-    ],
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _filter: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this._getCreateRepoCapability();
       this.fire('title-change', {title: 'Repos'});
       this._maybeOpenCreateOverlay(this.params);
-    },
+    }
 
     _paramsChanged(params) {
       this._loading = true;
@@ -86,7 +92,7 @@
 
       return this._getRepos(this._filter, this._reposPerPage,
           this._offset);
-    },
+    }
 
     /**
      * Opens the create overlay if the route has a hash 'create'
@@ -96,15 +102,15 @@
       if (params && params.openCreateModal) {
         this.$.createOverlay.open();
       }
-    },
+    }
 
     _computeRepoUrl(name) {
       return this.getUrl(this._path + '/', name);
-    },
+    }
 
     _computeChangesLink(name) {
       return Gerrit.Nav.getUrlForProjectChanges(name);
-    },
+    }
 
     _getCreateRepoCapability() {
       return this.$.restAPI.getAccount().then(account => {
@@ -116,7 +122,7 @@
               }
             });
       });
-    },
+    }
 
     _getRepos(filter, reposPerPage, offset) {
       this._repos = [];
@@ -127,36 +133,38 @@
             this._repos = repos;
             this._loading = false;
           });
-    },
+    }
 
     _refreshReposList() {
       this.$.restAPI.invalidateReposCache();
       return this._getRepos(this._filter, this._reposPerPage,
           this._offset);
-    },
+    }
 
     _handleCreateRepo() {
       this.$.createNewModal.handleCreateRepo().then(() => {
         this._refreshReposList();
       });
-    },
+    }
 
     _handleCloseCreate() {
       this.$.createOverlay.close();
-    },
+    }
 
     _handleCreateClicked() {
       this.$.createOverlay.open();
-    },
+    }
 
     _readOnly(item) {
       return item.state === 'READ_ONLY' ? 'Y' : '';
-    },
+    }
 
     _computeWeblink(repo) {
       if (!repo.web_links) { return ''; }
       const webLinks = repo.web_links;
       return webLinks.length ? webLinks : null;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoList.is, GrRepoList);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html
index c77592c..9569e56 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-list/gr-repo-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.html b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.html
index d2093e4..ef5b755 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.html
@@ -30,8 +30,12 @@
 
 <dom-module id="gr-repo-plugin-config">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-form-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-subpage-styles">
       .inherited {
         color: var(--deemphasized-text-color);
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
index 883a4e1..8658397 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
@@ -17,28 +17,32 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-plugin-config',
-
+  /**
+    * @appliesMixin Gerrit.RepoPluginConfigMixin
+    */
+  class GrRepoPluginConfig extends Polymer.mixinBehaviors( [
+    Gerrit.RepoPluginConfig,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-plugin-config'; }
     /**
      * Fired when the plugin config changes.
      *
      * @event plugin-config-changed
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      pluginData: Object,
-      /** @type {Array} */
-      _pluginConfigOptions: {
-        type: Array,
-        computed: '_computePluginConfigOptions(pluginData.*)',
-      },
-    },
-
-    behaviors: [
-      Gerrit.RepoPluginConfig,
-    ],
+        pluginData: Object,
+        /** @type {Array} */
+        _pluginConfigOptions: {
+          type: Array,
+          computed: '_computePluginConfigOptions(pluginData.*)',
+        },
+      };
+    }
 
     _computePluginConfigOptions(dataRecord) {
       if (!dataRecord || !dataRecord.base || !dataRecord.base.config) {
@@ -46,34 +50,34 @@
       }
       const {config} = dataRecord.base;
       return Object.keys(config).map(_key => ({_key, info: config[_key]}));
-    },
+    }
 
     _isArray(type) {
       return type === this.ENTRY_TYPES.ARRAY;
-    },
+    }
 
     _isBoolean(type) {
       return type === this.ENTRY_TYPES.BOOLEAN;
-    },
+    }
 
     _isList(type) {
       return type === this.ENTRY_TYPES.LIST;
-    },
+    }
 
     _isString(type) {
       // Treat numbers like strings for simplicity.
       return type === this.ENTRY_TYPES.STRING ||
           type === this.ENTRY_TYPES.INT ||
           type === this.ENTRY_TYPES.LONG;
-    },
+    }
 
     _computeDisabled(editable) {
       return editable === 'false';
-    },
+    }
 
     _computeChecked(value) {
       return JSON.parse(value);
-    },
+    }
 
     _handleStringChange(e) {
       const el = Polymer.dom(e).localTarget;
@@ -81,7 +85,7 @@
       const configChangeInfo =
           this._buildConfigChangeInfo(el.value, _key);
       this._handleChange(configChangeInfo);
-    },
+    }
 
     _handleListChange(e) {
       const el = Polymer.dom(e).localTarget;
@@ -89,7 +93,7 @@
       const configChangeInfo =
           this._buildConfigChangeInfo(el.value, _key);
       this._handleChange(configChangeInfo);
-    },
+    }
 
     _handleBooleanChange(e) {
       const el = Polymer.dom(e).localTarget;
@@ -97,7 +101,7 @@
       const configChangeInfo =
           this._buildConfigChangeInfo(JSON.stringify(el.checked), _key);
       this._handleChange(configChangeInfo);
-    },
+    }
 
     _buildConfigChangeInfo(value, _key) {
       const info = this.pluginData.config[_key];
@@ -107,11 +111,11 @@
         info,
         notifyPath: `${_key}.value`,
       };
-    },
+    }
 
     _handleArrayChange({detail}) {
       this._handleChange(detail);
-    },
+    }
 
     _handleChange({_key, info, notifyPath}) {
       const {name, config} = this.pluginData;
@@ -125,6 +129,8 @@
 
       this.dispatchEvent(new CustomEvent(
           this.PLUGIN_CONFIG_CHANGED, {detail, bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoPluginConfig.is, GrRepoPluginConfig);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html
index 0a6846f..ff0e522 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-plugin-config</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
index 3d8a2d2..5e37261 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
@@ -21,6 +21,7 @@
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 
 <link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
+<link rel="import" href="../../plugins/gr-endpoint-param/gr-endpoint-param.html">
 <link rel="import" href="../../shared/gr-download-commands/gr-download-commands.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../../shared/gr-select/gr-select.html">
@@ -31,7 +32,9 @@
 
 <dom-module id="gr-repo">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-subpage-styles">
       h2.edited:after {
         color: var(--deemphasized-text-color);
@@ -54,9 +57,13 @@
         display: block;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <main class="gr-form-styles read-only">
-      <style include="shared-styles"></style>
+      <style include="shared-styles">
+        /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+      </style>
       <div class="info">
         <h1 id="Title" class$="name">
           [[repo]]
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
index 153a137..5bd7d27a 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.js
@@ -51,76 +51,84 @@
     },
   };
 
-  Polymer({
-    is: 'gr-repo',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrRepo extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo'; }
 
-    properties: {
-      params: Object,
-      repo: String,
+    static get properties() {
+      return {
+        params: Object,
+        repo: String,
 
-      _configChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-        observer: '_loggedInChanged',
-      },
-      /** @type {?} */
-      _repoConfig: Object,
-      /** @type {?} */
-      _pluginData: {
-        type: Array,
-        computed: '_computePluginData(_repoConfig.plugin_config.*)',
-      },
-      _readOnly: {
-        type: Boolean,
-        value: true,
-      },
-      _states: {
-        type: Array,
-        value() {
-          return Object.values(STATES);
+        _configChanged: {
+          type: Boolean,
+          value: false,
         },
-      },
-      _submitTypes: {
-        type: Array,
-        value() {
-          return Object.values(SUBMIT_TYPES);
+        _loading: {
+          type: Boolean,
+          value: true,
         },
-      },
-      _schemes: {
-        type: Array,
-        value() { return []; },
-        computed: '_computeSchemes(_schemesObj)',
-        observer: '_schemesChanged',
-      },
-      _selectedCommand: {
-        type: String,
-        value: 'Clone',
-      },
-      _selectedScheme: String,
-      _schemesObj: Object,
-    },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+          observer: '_loggedInChanged',
+        },
+        /** @type {?} */
+        _repoConfig: Object,
+        /** @type {?} */
+        _pluginData: {
+          type: Array,
+          computed: '_computePluginData(_repoConfig.plugin_config.*)',
+        },
+        _readOnly: {
+          type: Boolean,
+          value: true,
+        },
+        _states: {
+          type: Array,
+          value() {
+            return Object.values(STATES);
+          },
+        },
+        _submitTypes: {
+          type: Array,
+          value() {
+            return Object.values(SUBMIT_TYPES);
+          },
+        },
+        _schemes: {
+          type: Array,
+          value() { return []; },
+          computed: '_computeSchemes(_schemesObj)',
+          observer: '_schemesChanged',
+        },
+        _selectedCommand: {
+          type: String,
+          value: 'Clone',
+        },
+        _selectedScheme: String,
+        _schemesObj: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_handleConfigChanged(_repoConfig.*)',
-    ],
+    static get observers() {
+      return [
+        '_handleConfigChanged(_repoConfig.*)',
+      ];
+    }
 
     attached() {
+      super.attached();
       this._loadRepo();
 
       this.fire('title-change', {title: this.repo});
-    },
+    }
 
     _computePluginData(configRecord) {
       if (!configRecord ||
@@ -129,7 +137,7 @@
       const pluginConfig = configRecord.base;
       return Object.keys(pluginConfig)
           .map(name => ({name, config: pluginConfig[name]}));
-    },
+    }
 
     _loadRepo() {
       if (!this.repo) { return Promise.resolve(); }
@@ -179,15 +187,15 @@
       }));
 
       return Promise.all(promises);
-    },
+    }
 
     _computeLoadingClass(loading) {
       return loading ? 'loading' : '';
-    },
+    }
 
     _computeHideClass(arr) {
       return !arr || !arr.length ? 'hide' : '';
-    },
+    }
 
     _loggedInChanged(_loggedIn) {
       if (!_loggedIn) { return; }
@@ -197,7 +205,7 @@
           this._selectedScheme = prefs.download_scheme.toLowerCase();
         }
       });
-    },
+    }
 
     _formatBooleanSelect(item) {
       if (!item) { return; }
@@ -218,7 +226,7 @@
           value: 'FALSE',
         },
       ];
-    },
+    }
 
     _formatSubmitTypeSelect(projectConfig) {
       if (!projectConfig) { return; }
@@ -248,15 +256,15 @@
         },
         ...allValues,
       ];
-    },
+    }
 
     _isLoading() {
       return this._loading || this._loading === undefined;
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _formatRepoConfigForSave(repoConfig) {
       const configInputObj = {};
@@ -278,38 +286,38 @@
         }
       }
       return configInputObj;
-    },
+    }
 
     _handleSaveRepoConfig() {
       return this.$.restAPI.saveRepoConfig(this.repo,
           this._formatRepoConfigForSave(this._repoConfig)).then(() => {
         this._configChanged = false;
       });
-    },
+    }
 
     _handleConfigChanged() {
       if (this._isLoading()) { return; }
       this._configChanged = true;
-    },
+    }
 
     _computeButtonDisabled(readOnly, configChanged) {
       return readOnly || !configChanged;
-    },
+    }
 
     _computeHeaderClass(configChanged) {
       return configChanged ? 'edited' : '';
-    },
+    }
 
     _computeSchemes(schemesObj) {
       return Object.keys(schemesObj);
-    },
+    }
 
     _schemesChanged(schemes) {
       if (schemes.length === 0) { return; }
       if (!schemes.includes(this._selectedScheme)) {
         this._selectedScheme = schemes.sort()[0];
       }
-    },
+    }
 
     _computeCommands(repo, schemesObj, _selectedScheme) {
       if (!schemesObj || !repo || !_selectedScheme) {
@@ -331,19 +339,21 @@
         });
       }
       return commands;
-    },
+    }
 
     _computeRepositoriesClass(config) {
       return config ? 'showConfig': '';
-    },
+    }
 
     _computeChangesUrl(name) {
       return Gerrit.Nav.getUrlForProjectChanges(name);
-    },
+    }
 
     _handlePluginConfigChanged({detail: {name, config, notifyPath}}) {
       this._repoConfig.plugin_config[name] = config;
       this.notifyPath('_repoConfig.plugin_config.' + notifyPath);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepo.is, GrRepo);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
index 4e81565..102a45e 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
index 9ec8985..9820e31 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
@@ -16,6 +16,7 @@
 -->
 
 <link rel="import" href="/bower_components/polymer/polymer.html">
+<link rel="import" href="/bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
 
 <link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
@@ -25,6 +26,7 @@
 <link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-select/gr-select.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-rule-editor">
   <template>
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
index df5a9f3..7c00787 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
@@ -63,62 +63,76 @@
     },
   ];
 
-  Polymer({
-    is: 'gr-rule-editor',
-
-    properties: {
-      hasRange: Boolean,
-      /** @type {?} */
-      label: Object,
-      editing: {
-        type: Boolean,
-        value: false,
-        observer: '_handleEditingChanged',
-      },
-      groupId: String,
-      groupName: String,
-      permission: String,
-      /** @type {?} */
-      rule: {
-        type: Object,
-        notify: true,
-      },
-      section: String,
-
-      _deleted: {
-        type: Boolean,
-        value: false,
-      },
-      _originalRuleValues: Object,
-    },
-
-    behaviors: [
-      Gerrit.AccessBehavior,
-      Gerrit.BaseUrlBehavior,
-      /**
+  /**
+    * @appliesMixin Gerrit.AccessMixin
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrRuleEditor extends Polymer.mixinBehaviors( [
+    Gerrit.AccessBehavior,
+    Gerrit.BaseUrlBehavior,
+    /**
        * Unused in this element, but called by other elements in tests
        * e.g gr-permission_test.
        */
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-rule-editor'; }
 
-    observers: [
-      '_handleValueChange(rule.value.*)',
-    ],
+    static get properties() {
+      return {
+        hasRange: Boolean,
+        /** @type {?} */
+        label: Object,
+        editing: {
+          type: Boolean,
+          value: false,
+          observer: '_handleEditingChanged',
+        },
+        groupId: String,
+        groupName: String,
+        permission: String,
+        /** @type {?} */
+        rule: {
+          type: Object,
+          notify: true,
+        },
+        section: String,
 
-    listeners: {
-      'access-saved': '_handleAccessSaved',
-    },
+        _deleted: {
+          type: Boolean,
+          value: false,
+        },
+        _originalRuleValues: Object,
+      };
+    }
+
+    static get observers() {
+      return [
+        '_handleValueChange(rule.value.*)',
+      ];
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('access-saved',
+          () => this._handleAccessSaved());
+    }
 
     ready() {
+      super.ready();
       // Called on ready rather than the observer because when new rules are
       // added, the observer is triggered prior to being ready.
       if (!this.rule) { return; } // Check needed for test purposes.
       this._setupValues(this.rule);
-    },
+    }
 
     attached() {
+      super.attached();
       if (!this.rule) { return; } // Check needed for test purposes.
       if (!this._originalRuleValues) {
         // Observer _handleValueChange is called after the ready()
@@ -126,13 +140,13 @@
         // avoid set .modified flag to true
         this._setOriginalRuleValues(this.rule.value);
       }
-    },
+    }
 
     _setupValues(rule) {
       if (!rule.value) {
         this._setDefaultRuleValues();
       }
-    },
+    }
 
     _computeForce(permission, action) {
       if (this.permissionValues.push.id === permission &&
@@ -141,21 +155,21 @@
       }
 
       return this.permissionValues.editTopicName.id === permission;
-    },
+    }
 
     _computeForceClass(permission, action) {
       return this._computeForce(permission, action) ? 'force' : '';
-    },
+    }
 
     _computeGroupPath(group) {
       return `${this.getBaseUrl()}/admin/groups/${this.encodeURL(group, true)}`;
-    },
+    }
 
     _handleAccessSaved() {
       // Set a new 'original' value to keep track of after the value has been
       // saved.
       this._setOriginalRuleValues(this.rule.value);
-    },
+    }
 
     _handleEditingChanged(editing, editingOld) {
       // Ignore when editing gets set initially.
@@ -164,7 +178,7 @@
       if (!editing) {
         this._handleUndoChange();
       }
-    },
+    }
 
     _computeSectionClass(editing, deleted) {
       const classList = [];
@@ -175,7 +189,7 @@
         classList.push('deleted');
       }
       return classList.join(' ');
-    },
+    }
 
     _computeForceOptions(permission, action) {
       if (permission === this.permissionValues.push.id) {
@@ -190,7 +204,7 @@
         return FORCE_EDIT_OPTIONS;
       }
       return [];
-    },
+    }
 
     _getDefaultRuleValues(permission, label) {
       const ruleAction = Action.ALLOW;
@@ -207,19 +221,19 @@
       }
       value.action = DROPDOWN_OPTIONS[0];
       return value;
-    },
+    }
 
     _setDefaultRuleValues() {
       this.set('rule.value', this._getDefaultRuleValues(this.permission,
           this.label));
-    },
+    }
 
     _computeOptions(permission) {
       if (permission === 'priority') {
         return PRIORITY_OPTIONS;
       }
       return DROPDOWN_OPTIONS;
-    },
+    }
 
     _handleRemoveRule() {
       if (this.rule.value.added) {
@@ -230,12 +244,12 @@
       this.rule.value.deleted = true;
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _handleUndoRemove() {
       this._deleted = false;
       delete this.rule.value.deleted;
-    },
+    }
 
     _handleUndoChange() {
       // gr-permission will take care of removing rules that were added but
@@ -245,7 +259,7 @@
       this._deleted = false;
       delete this.rule.value.deleted;
       delete this.rule.value.modified;
-    },
+    }
 
     _handleValueChange() {
       if (!this._originalRuleValues) { return; }
@@ -253,10 +267,12 @@
       // Allows overall access page to know a change has been made.
       this.dispatchEvent(
           new CustomEvent('access-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _setOriginalRuleValues(value) {
       this._originalRuleValues = Object.assign({}, value);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRuleEditor.is, GrRuleEditor);
 })();
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
index 6d533af..dbf5bb0 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-rule-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
index 533b867..b7e615c 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
@@ -29,6 +29,8 @@
 <link rel="import" href="../../shared/gr-limited-text/gr-limited-text.html">
 <link rel="import" href="../../shared/gr-tooltip-content/gr-tooltip-content.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
+<link rel="import" href="../../plugins/gr-endpoint-param/gr-endpoint-param.html">
 
 <dom-module id="gr-change-list-item">
   <template>
@@ -123,7 +125,9 @@
         }
       }
     </style>
-    <style include="gr-change-list-styles"></style>
+    <style include="gr-change-list-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <td class="cell leftPadding"></td>
     <td class="cell star" hidden$="[[!showStar]]" hidden>
       <gr-change-star change="{{change}}"></gr-change-star>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index 8eb39891..3ce87f8 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -24,57 +24,67 @@
     LARGE: 1000,
   };
 
-  Polymer({
-    is: 'gr-change-list-item',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.ChangeTableMixin
+    * @appliesMixin Gerrit.PathListMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeListItem extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.ChangeTableBehavior,
+    Gerrit.PathListBehavior,
+    Gerrit.RESTClientBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list-item'; }
 
-    properties: {
-      visibleChangeTableColumns: Array,
-      labelNames: {
-        type: Array,
-      },
+    static get properties() {
+      return {
+        visibleChangeTableColumns: Array,
+        labelNames: {
+          type: Array,
+        },
 
-      /** @type {?} */
-      change: Object,
-      changeURL: {
-        type: String,
-        computed: '_computeChangeURL(change)',
-      },
-      statuses: {
-        type: Array,
-        computed: 'changeStatuses(change)',
-      },
-      showStar: {
-        type: Boolean,
-        value: false,
-      },
-      showNumber: Boolean,
-      _changeSize: {
-        type: String,
-        computed: '_computeChangeSize(change)',
-      },
-      _dynamicCellEndpoints: {
-        type: Array,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.ChangeTableBehavior,
-      Gerrit.PathListBehavior,
-      Gerrit.RESTClientBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+        /** @type {?} */
+        change: Object,
+        changeURL: {
+          type: String,
+          computed: '_computeChangeURL(change)',
+        },
+        statuses: {
+          type: Array,
+          computed: 'changeStatuses(change)',
+        },
+        showStar: {
+          type: Boolean,
+          value: false,
+        },
+        showNumber: Boolean,
+        _changeSize: {
+          type: String,
+          computed: '_computeChangeSize(change)',
+        },
+        _dynamicCellEndpoints: {
+          type: Array,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       Gerrit.awaitPluginsLoaded().then(() => {
         this._dynamicCellEndpoints = Gerrit._endpoints.getDynamicEndpoints(
             'change-list-item-cell');
       });
-    },
+    }
 
     _computeChangeURL(change) {
       return Gerrit.Nav.getUrlForChange(change);
-    },
+    }
 
     _computeLabelTitle(change, labelName) {
       const label = change.labels[labelName];
@@ -85,7 +95,7 @@
         return labelName + '\nby ' + significantLabel.name;
       }
       return labelName;
-    },
+    }
 
     _computeLabelClass(change, labelName) {
       const label = change.labels[labelName];
@@ -112,7 +122,7 @@
         classes['u-gray-background'] = true;
       }
       return Object.keys(classes).sort().join(' ');
-    },
+    }
 
     _computeLabelValue(change, labelName) {
       const label = change.labels[labelName];
@@ -130,22 +140,22 @@
         return label.value;
       }
       return '';
-    },
+    }
 
     _computeRepoUrl(change) {
       return Gerrit.Nav.getUrlForProjectChanges(change.project, true,
           change.internalHost);
-    },
+    }
 
     _computeRepoBranchURL(change) {
       return Gerrit.Nav.getUrlForBranch(change.branch, change.project, null,
           change.internalHost);
-    },
+    }
 
     _computeTopicURL(change) {
       if (!change.topic) { return ''; }
       return Gerrit.Nav.getUrlForTopic(change.topic, change.internalHost);
-    },
+    }
 
     /**
      * Computes the display string for the project column. If there is a host
@@ -162,7 +172,7 @@
       if (change.internalHost) { str += change.internalHost + '/'; }
       str += truncate ? this.truncatePath(change.project, 2) : change.project;
       return str;
-    },
+    }
 
     _computeSizeTooltip(change) {
       if (change.insertions + change.deletions === 0 ||
@@ -171,7 +181,7 @@
       } else {
         return `+${change.insertions}, -${change.deletions}`;
       }
-    },
+    }
 
     /**
      * TShirt sizing is based on the following paper:
@@ -193,7 +203,7 @@
       } else {
         return 'XL';
       }
-    },
+    }
 
     toggleReviewed() {
       const newVal = !this.change.reviewed;
@@ -203,6 +213,8 @@
         composed: true,
         detail: {change: this.change, reviewed: newVal},
       }));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeListItem.is, GrChangeListItem);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
index 12b4202..3c402d1 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-list-item</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
index 02e9a04..49aa1eb 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
@@ -29,44 +29,49 @@
 
   const LIMIT_OPERATOR_PATTERN = /\blimit:(\d+)/i;
 
-  Polymer({
-    is: 'gr-change-list-view',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeListView extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list-view'; }
     /**
      * Fired when the title of the page should change.
      *
      * @event title-change
      */
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      /**
+        /**
        * True when user is logged in.
        */
-      _loggedIn: {
-        type: Boolean,
-        computed: '_computeLoggedIn(account)',
-      },
+        _loggedIn: {
+          type: Boolean,
+          computed: '_computeLoggedIn(account)',
+        },
 
-      account: {
-        type: Object,
-        value: null,
-      },
+        account: {
+          type: Object,
+          value: null,
+        },
 
-      /**
+        /**
        * State persisted across restamps of the element.
        *
        * Need sub-property declaration since it is used in template before
@@ -74,66 +79,71 @@
        * @type {{ selectedChangeIndex: (number|undefined) }}
        *
        */
-      viewState: {
-        type: Object,
-        notify: true,
-        value() { return {}; },
-      },
+        viewState: {
+          type: Object,
+          notify: true,
+          value() { return {}; },
+        },
 
-      preferences: Object,
+        preferences: Object,
 
-      _changesPerPage: Number,
+        _changesPerPage: Number,
 
-      /**
+        /**
        * Currently active query.
        */
-      _query: {
-        type: String,
-        value: '',
-      },
+        _query: {
+          type: String,
+          value: '',
+        },
 
-      /**
+        /**
        * Offset of currently visible query results.
        */
-      _offset: Number,
+        _offset: Number,
 
-      /**
+        /**
        * Change objects loaded from the server.
        */
-      _changes: {
-        type: Array,
-        observer: '_changesChanged',
-      },
+        _changes: {
+          type: Array,
+          observer: '_changesChanged',
+        },
 
-      /**
+        /**
        * For showing a "loading..." string during ajax requests.
        */
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
 
-      /** @type {?String} */
-      _userId: {
-        type: String,
-        value: null,
-      },
+        /** @type {?String} */
+        _userId: {
+          type: String,
+          value: null,
+        },
 
-      /** @type {?String} */
-      _repo: {
-        type: String,
-        value: null,
-      },
-    },
+        /** @type {?String} */
+        _repo: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
-    listeners: {
-      'next-page': '_handleNextPage',
-      'previous-page': '_handlePreviousPage',
-    },
+    created() {
+      super.created();
+      this.addEventListener('next-page',
+          () => this._handleNextPage());
+      this.addEventListener('previous-page',
+          () => this._handlePreviousPage());
+    }
 
     attached() {
+      super.attached();
       this._loadPreferences();
-    },
+    }
 
     _paramsChanged(value) {
       if (value.view !== Gerrit.Nav.View.SEARCH) { return; }
@@ -170,7 +180,7 @@
         this._changes = changes;
         this._loading = false;
       });
-    },
+    }
 
     _loadPreferences() {
       return this.$.restAPI.getLoggedIn().then(loggedIn => {
@@ -182,20 +192,20 @@
           this.preferences = {};
         }
       });
-    },
+    }
 
     _replaceCurrentLocation(url) {
       window.location.replace(url);
-    },
+    }
 
     _getChanges() {
       return this.$.restAPI.getChanges(this._changesPerPage, this._query,
           this._offset);
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     _limitFor(query, defaultLimit) {
       const match = query.match(LIMIT_OPERATOR_PATTERN);
@@ -203,7 +213,7 @@
         return defaultLimit;
       }
       return parseInt(match[1], 10);
-    },
+    }
 
     _computeNavLink(query, offset, direction, changesPerPage) {
       // Offset could be a string when passed from the router.
@@ -211,32 +221,32 @@
       const limit = this._limitFor(query, changesPerPage);
       const newOffset = Math.max(0, offset + (limit * direction));
       return Gerrit.Nav.getUrlForSearchQuery(query, newOffset);
-    },
+    }
 
     _computePrevArrowClass(offset) {
       return offset === 0 ? 'hide' : '';
-    },
+    }
 
     _computeNextArrowClass(changes) {
       const more = changes.length && changes[changes.length - 1]._more_changes;
       return more ? '' : 'hide';
-    },
+    }
 
     _computeNavClass(loading) {
       return loading || !this._changes || !this._changes.length ? 'hide' : '';
-    },
+    }
 
     _handleNextPage() {
       if (this.$.nextArrow.hidden) { return; }
       page.show(this._computeNavLink(
           this._query, this._offset, 1, this._changesPerPage));
-    },
+    }
 
     _handlePreviousPage() {
       if (this.$.prevArrow.hidden) { return; }
       page.show(this._computeNavLink(
           this._query, this._offset, -1, this._changesPerPage));
-    },
+    }
 
     _changesChanged(changes) {
       this._userId = null;
@@ -255,28 +265,30 @@
       if (REPO_QUERY_PATTERN.test(this._query)) {
         this._repo = changes[0].project;
       }
-    },
+    }
 
     _computeHeaderClass(id) {
       return id ? '' : 'hide';
-    },
+    }
 
     _computePage(offset, changesPerPage) {
       return offset / changesPerPage + 1;
-    },
+    }
 
     _computeLoggedIn(account) {
       return !!(account && Object.keys(account).length > 0);
-    },
+    }
 
     _handleToggleStar(e) {
       this.$.restAPI.saveChangeStarred(e.detail.change._number,
           e.detail.starred);
-    },
+    }
 
     _handleToggleReviewed(e) {
       this.$.restAPI.saveChangeReviewed(e.detail.change._number,
           e.detail.reviewed);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeListView.is, GrChangeListView);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html
index 2367aac..08a83af 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-list-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
index 325bee0..8fdb90c 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
@@ -27,10 +27,13 @@
 <link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.html">
 <link rel="import" href="../gr-change-list-item/gr-change-list-item.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
 
 <dom-module id="gr-change-list">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-change-list-styles">
       #changeList {
         border-collapse: collapse;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index 5006f1e..5ac4fcd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -22,9 +22,25 @@
   const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
   const MAX_SHORTCUT_CHARS = 5;
 
-  Polymer({
-    is: 'gr-change-list',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.ChangeTableMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeList extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.ChangeTableBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.RESTClientBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list'; }
     /**
      * Fired when next page key shortcut was pressed.
      *
@@ -37,28 +53,25 @@
      * @event previous-page
      */
 
-    hostAttributes: {
-      tabindex: 0,
-    },
-
-    properties: {
+    static get properties() {
+      return {
       /**
        * The logged-in user's account, or an empty object if no user is logged
        * in.
        */
-      account: {
-        type: Object,
-        value: null,
-      },
-      /**
+        account: {
+          type: Object,
+          value: null,
+        },
+        /**
        * An array of ChangeInfo objects to render.
        * https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info
        */
-      changes: {
-        type: Array,
-        observer: '_changesChanged',
-      },
-      /**
+        changes: {
+          type: Array,
+          observer: '_changesChanged',
+        },
+        /**
        * ChangeInfo objects grouped into arrays. The sections and changes
        * properties should not be used together.
        *
@@ -68,56 +81,46 @@
        *   results: !Array<!Object>
        * }>}
        */
-      sections: {
-        type: Array,
-        value() { return []; },
-      },
-      labelNames: {
-        type: Array,
-        computed: '_computeLabelNames(sections)',
-      },
-      _dynamicHeaderEndpoints: {
-        type: Array,
-      },
-      selectedIndex: {
-        type: Number,
-        notify: true,
-      },
-      showNumber: Boolean, // No default value to prevent flickering.
-      showStar: {
-        type: Boolean,
-        value: false,
-      },
-      showReviewedState: {
-        type: Boolean,
-        value: false,
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      changeTableColumns: Array,
-      visibleChangeTableColumns: Array,
-      preferences: Object,
-    },
+        sections: {
+          type: Array,
+          value() { return []; },
+        },
+        labelNames: {
+          type: Array,
+          computed: '_computeLabelNames(sections)',
+        },
+        _dynamicHeaderEndpoints: {
+          type: Array,
+        },
+        selectedIndex: {
+          type: Number,
+          notify: true,
+        },
+        showNumber: Boolean, // No default value to prevent flickering.
+        showStar: {
+          type: Boolean,
+          value: false,
+        },
+        showReviewedState: {
+          type: Boolean,
+          value: false,
+        },
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        changeTableColumns: Array,
+        visibleChangeTableColumns: Array,
+        preferences: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.ChangeTableBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.RESTClientBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    listeners: {
-      keydown: '_scopedKeydownHandler',
-    },
-
-    observers: [
-      '_sectionsChanged(sections.*)',
-      '_computePreferences(account, preferences)',
-    ],
+    static get observers() {
+      return [
+        '_sectionsChanged(sections.*)',
+        '_computePreferences(account, preferences)',
+      ];
+    }
 
     keyboardShortcuts() {
       return {
@@ -130,14 +133,26 @@
         [this.Shortcut.TOGGLE_CHANGE_STAR]: '_toggleChangeStar',
         [this.Shortcut.REFRESH_CHANGE_LIST]: '_refreshChangeList',
       };
-    },
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('keydown',
+          e => this._scopedKeydownHandler(e));
+    }
+
+    ready() {
+      super.ready();
+      this._ensureAttribute('tabindex', 0);
+    }
 
     attached() {
+      super.attached();
       Gerrit.awaitPluginsLoaded().then(() => {
         this._dynamicHeaderEndpoints = Gerrit._endpoints.getDynamicEndpoints(
             'change-list-header');
       });
-    },
+    }
 
     /**
      * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
@@ -151,11 +166,11 @@
         // Enter.
         this._openChange(e);
       }
-    },
+    }
 
     _lowerCase(column) {
       return column.toLowerCase();
-    },
+    }
 
     _computePreferences(account, preferences) {
       // Polymer 2: check for undefined
@@ -175,13 +190,13 @@
         this.showNumber = false;
         this.visibleChangeTableColumns = this.columnNames;
       }
-    },
+    }
 
     _computeColspan(changeTableColumns, labelNames) {
       if (!changeTableColumns || !labelNames) return;
       return changeTableColumns.length + labelNames.length +
           NUMBER_FIXED_COLUMNS;
-    },
+    }
 
     _computeLabelNames(sections) {
       if (!sections) { return []; }
@@ -198,7 +213,7 @@
         }
       }
       return labels.sort();
-    },
+    }
 
     _computeLabelShortcut(labelName) {
       if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
@@ -210,11 +225,11 @@
             return a + i[0].toUpperCase();
           }, '')
           .slice(0, MAX_SHORTCUT_CHARS);
-    },
+    }
 
     _changesChanged(changes) {
       this.sections = changes ? [{results: changes}] : [];
-    },
+    }
 
     _processQuery(query) {
       let tokens = query.split(' ');
@@ -225,11 +240,11 @@
         });
       });
       return tokens.join(' ');
-    },
+    }
 
     _sectionHref(query) {
       return Gerrit.Nav.getUrlForSearchQuery(this._processQuery(query));
-    },
+    }
 
     /**
      * Maps an index local to a particular section to the absolute index
@@ -245,19 +260,19 @@
         idx += this.sections[i].results.length;
       }
       return idx + localIndex;
-    },
+    }
 
     _computeItemSelected(sectionIndex, index, selectedIndex) {
       const idx = this._computeItemAbsoluteIndex(sectionIndex, index);
       return idx == selectedIndex;
-    },
+    }
 
     _computeItemNeedsReview(account, change, showReviewedState) {
       return showReviewedState && !change.reviewed &&
           !change.work_in_progress &&
           this.changeIsOpen(change) &&
           (!account || account._account_id != change.owner._account_id);
-    },
+    }
 
     _computeItemHighlight(account, change) {
       // Do not show the assignee highlight if the change is not open.
@@ -267,7 +282,7 @@
         return false;
       }
       return account._account_id === change.assignee._account_id;
-    },
+    }
 
     _nextChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -275,7 +290,7 @@
 
       e.preventDefault();
       this.$.cursor.next();
-    },
+    }
 
     _prevChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -283,7 +298,7 @@
 
       e.preventDefault();
       this.$.cursor.previous();
-    },
+    }
 
     _openChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -291,7 +306,7 @@
 
       e.preventDefault();
       Gerrit.Nav.navigateToChange(this._changeForIndex(this.selectedIndex));
-    },
+    }
 
     _nextPage(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -301,7 +316,7 @@
 
       e.preventDefault();
       this.fire('next-page');
-    },
+    }
 
     _prevPage(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -311,7 +326,7 @@
 
       e.preventDefault();
       this.fire('previous-page');
-    },
+    }
 
     _toggleChangeReviewed(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -319,7 +334,7 @@
 
       e.preventDefault();
       this._toggleReviewedForIndex(this.selectedIndex);
-    },
+    }
 
     _toggleReviewedForIndex(index) {
       const changeEls = this._getListItems();
@@ -329,18 +344,18 @@
 
       const changeEl = changeEls[index];
       changeEl.toggleReviewed();
-    },
+    }
 
     _refreshChangeList(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       e.preventDefault();
       this._reloadWindow();
-    },
+    }
 
     _reloadWindow() {
       window.location.reload();
-    },
+    }
 
     _toggleChangeStar(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -348,7 +363,7 @@
 
       e.preventDefault();
       this._toggleStarForIndex(this.selectedIndex);
-    },
+    }
 
     _toggleStarForIndex(index) {
       const changeEls = this._getListItems();
@@ -358,7 +373,7 @@
 
       const changeEl = changeEls[index];
       changeEl.$$('gr-change-star').toggleStar();
-    },
+    }
 
     _changeForIndex(index) {
       const changeEls = this._getListItems();
@@ -366,12 +381,12 @@
         return changeEls[index].change;
       }
       return null;
-    },
+    }
 
     _getListItems() {
       return Array.from(
           Polymer.dom(this.root).querySelectorAll('gr-change-list-item'));
-    },
+    }
 
     _sectionsChanged() {
       // Flush DOM operations so that the list item elements will be loaded.
@@ -379,14 +394,16 @@
         this.$.cursor.stops = this._getListItems();
         this.$.cursor.moveToStart();
       });
-    },
+    }
 
     _isOutgoing(section) {
       return !!section.isOutgoing;
-    },
+    }
 
     _isEmpty(section) {
       return !section.results.length;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeList.is, GrChangeList);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
index 817de6f..75fd167 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
index 19e7a25..e6caacb 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
@@ -17,8 +17,10 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-create-change-help',
+  class GrCreateChangeHelp extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-change-help'; }
 
     /**
      * Fired when the "Create change" button is tapped.
@@ -30,6 +32,8 @@
       e.preventDefault();
       this.dispatchEvent(
           new CustomEvent('create-tap', {bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateChangeHelp.is, GrCreateChangeHelp);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html
index c43d62a..f10fbf2 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-change-help</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
index 5abb257..303128b 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
@@ -23,37 +23,43 @@
     PUSH_PREFIX: 'git push origin HEAD:refs/for/',
   };
 
-  Polymer({
-    is: 'gr-create-commands-dialog',
+  class GrCreateCommandsDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-commands-dialog'; }
 
-    properties: {
-      branch: String,
-      _createNewCommitCommand: {
-        type: String,
-        readonly: true,
-        value: Commands.CREATE,
-      },
-      _amendExistingCommitCommand: {
-        type: String,
-        readonly: true,
-        value: Commands.AMEND,
-      },
-      _pushCommand: {
-        type: String,
-        computed: '_computePushCommand(branch)',
-      },
-    },
+    static get properties() {
+      return {
+        branch: String,
+        _createNewCommitCommand: {
+          type: String,
+          readonly: true,
+          value: Commands.CREATE,
+        },
+        _amendExistingCommitCommand: {
+          type: String,
+          readonly: true,
+          value: Commands.AMEND,
+        },
+        _pushCommand: {
+          type: String,
+          computed: '_computePushCommand(branch)',
+        },
+      };
+    }
 
     open() {
       this.$.commandsOverlay.open();
-    },
+    }
 
     _handleClose() {
       this.$.commandsOverlay.close();
-    },
+    }
 
     _computePushCommand(branch) {
       return Commands.PUSH_PREFIX + branch;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateCommandsDialog.is, GrCreateCommandsDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
index 89ad573..2228b50 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-create-commands-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
index d601cad..3652e70 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
@@ -23,37 +23,44 @@
    *
    * @event confirm
    */
+  class GrCreateDestinationDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-destination-dialog'; }
 
-  Polymer({
-    is: 'gr-create-destination-dialog',
+    static get properties() {
+      return {
+        _repo: String,
+        _branch: String,
+        _repoAndBranchSelected: {
+          type: Boolean,
+          value: false,
+          computed: '_computeRepoAndBranchSelected(_repo, _branch)',
+        },
+      };
+    }
 
-    properties: {
-      _repo: String,
-      _branch: String,
-      _repoAndBranchSelected: {
-        type: Boolean,
-        value: false,
-        computed: '_computeRepoAndBranchSelected(_repo, _branch)',
-      },
-    },
     open() {
       this._repo = '';
       this._branch = '';
       this.$.createOverlay.open();
-    },
+    }
 
     _handleClose() {
       this.$.createOverlay.close();
-    },
+    }
 
     _pickerConfirm() {
       this.$.createOverlay.close();
       const detail = {repo: this._repo, branch: this._branch};
       this.dispatchEvent(new CustomEvent('confirm', {detail, bubbles: false}));
-    },
+    }
 
     _computeRepoAndBranchSelected(repo, branch) {
       return !!(repo && branch);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateDestinationDialog.is,
+      GrCreateDestinationDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index b762ab3..69cc070 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -19,65 +19,72 @@
 
   const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g;
 
-  Polymer({
-    is: 'gr-dashboard-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrDashboardView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-dashboard-view'; }
     /**
      * Fired when the title of the page should change.
      *
      * @event title-change
      */
 
-    properties: {
-      account: {
-        type: Object,
-        value: null,
-      },
-      preferences: Object,
-      /** @type {{ selectedChangeIndex: number }} */
-      viewState: Object,
-
-      /** @type {{ project: string, user: string }} */
-      params: {
-        type: Object,
-      },
-
-      createChangeTap: {
-        type: Function,
-        value() {
-          return this._createChangeTap.bind(this);
+    static get properties() {
+      return {
+        account: {
+          type: Object,
+          value: null,
         },
-      },
+        preferences: Object,
+        /** @type {{ selectedChangeIndex: number }} */
+        viewState: Object,
 
-      _results: Array,
+        /** @type {{ project: string, user: string }} */
+        params: {
+          type: Object,
+        },
 
-      /**
+        createChangeTap: {
+          type: Function,
+          value() {
+            return this._createChangeTap.bind(this);
+          },
+        },
+
+        _results: Array,
+
+        /**
        * For showing a "loading..." string during ajax requests.
        */
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
 
-      _showDraftsBanner: {
-        type: Boolean,
-        value: false,
-      },
+        _showDraftsBanner: {
+          type: Boolean,
+          value: false,
+        },
 
-      _showNewUserHelp: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _showNewUserHelp: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    observers: [
-      '_paramsChanged(params.*)',
-    ],
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
+    static get observers() {
+      return [
+        '_paramsChanged(params.*)',
+      ];
+    }
 
     get options() {
       return this.listChangesOptionsToHex(
@@ -85,11 +92,12 @@
           this.ListChangesOption.DETAILED_ACCOUNTS,
           this.ListChangesOption.REVIEWED
       );
-    },
+    }
 
     attached() {
+      super.attached();
       this._loadPreferences();
-    },
+    }
 
     _loadPreferences() {
       return this.$.restAPI.getLoggedIn().then(loggedIn => {
@@ -101,7 +109,7 @@
           this.preferences = {};
         }
       });
-    },
+    }
 
     _getProjectDashboard(project, dashboard) {
       const errFn = response => {
@@ -124,18 +132,18 @@
           }),
         };
       });
-    },
+    }
 
     _computeTitle(user) {
       if (!user || user === 'self') {
         return 'My Reviews';
       }
       return 'Dashboard for ' + user;
-    },
+    }
 
     _isViewActive(params) {
       return params.view === Gerrit.Nav.View.DASHBOARD;
-    },
+    }
 
     _paramsChanged(paramsChangeRecord) {
       const params = paramsChangeRecord.base;
@@ -145,7 +153,7 @@
       }
 
       return this._reload();
-    },
+    }
 
     /**
      * Reloads the element.
@@ -179,7 +187,7 @@
             });
             console.warn(err);
           }).then(() => { this._loading = false; });
-    },
+    }
 
     /**
      * Fetches the changes for each dashboard section and sets this._results
@@ -218,7 +226,7 @@
               !res.sections[i].hideIfEmpty ||
                 section.results.length));
           });
-    },
+    }
 
     _computeSectionCountLabel(changes) {
       if (!changes || !changes.length || changes.length == 0) {
@@ -228,7 +236,7 @@
       const numChanges = changes.length;
       const andMore = more ? ' and more' : '';
       return `(${numChanges}${andMore})`;
-    },
+    }
 
     _computeUserHeaderClass(params) {
       if (!params || !!params.project || !params.user
@@ -236,17 +244,17 @@
         return 'hide';
       }
       return '';
-    },
+    }
 
     _handleToggleStar(e) {
       this.$.restAPI.saveChangeStarred(e.detail.change._number,
           e.detail.starred);
-    },
+    }
 
     _handleToggleReviewed(e) {
       this.$.restAPI.saveChangeReviewed(e.detail.change._number,
           e.detail.reviewed);
-    },
+    }
 
     /**
      * Banner is shown if a user is on their own dashboard and they have draft
@@ -265,15 +273,15 @@
       if (!closedChanges.length) { return; }
 
       this._showDraftsBanner = true;
-    },
+    }
 
     _computeBannerClass(show) {
       return show ? '' : 'hide';
-    },
+    }
 
     _handleOpenDeleteDialog() {
       this.$.confirmDeleteOverlay.open();
-    },
+    }
 
     _handleConfirmDelete() {
       this.$.confirmDeleteDialog.disabled = true;
@@ -281,23 +289,25 @@
         this._closeConfirmDeleteOverlay();
         this._reload();
       });
-    },
+    }
 
     _closeConfirmDeleteOverlay() {
       this.$.confirmDeleteOverlay.close();
-    },
+    }
 
     _computeDraftsLink() {
       return Gerrit.Nav.getUrlForSearchQuery('has:draft -is:open');
-    },
+    }
 
     _createChangeTap(e) {
       this.$.destinationDialog.open();
-    },
+    }
 
     _handleDestinationConfirm(e) {
       this.$.commandsDialog.branch = e.detail.branch;
       this.$.commandsDialog.open();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDashboardView.is, GrDashboardView);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
index 41d4192..0d15d13 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-dashboard-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
index acc4295..96dcb98 100644
--- a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
+++ b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
@@ -17,14 +17,20 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-embed-dashboard',
+  class GrEmbedDashboard extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-embed-dashboard'; }
 
-    properties: {
-      account: Object,
-      sections: Array,
-      preferences: Object,
-      showNewUserHelp: Boolean,
-    },
-  });
+    static get properties() {
+      return {
+        account: Object,
+        sections: Array,
+        preferences: Object,
+        showNewUserHelp: Boolean,
+      };
+    }
+  }
+
+  customElements.define(GrEmbedDashboard.is, GrEmbedDashboard);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.html b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.html
index 0b4459c..5d4b8a3 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.html
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.html
@@ -24,8 +24,12 @@
 
 <dom-module id="gr-repo-header">
   <template>
-    <style include="shared-styles"></style>
-    <style include="dashboard-header-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="dashboard-header-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="info">
       <h1 class$="name">
         [[repo]]
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
index 7ae4dab..c603c45 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
@@ -17,18 +17,22 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-header',
+  class GrRepoHeader extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-repo-header'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?String} */
-      repo: {
-        type: String,
-        observer: '_repoChanged',
-      },
-      /** @type {String|null} */
-      _repoUrl: String,
-    },
+        repo: {
+          type: String,
+          observer: '_repoChanged',
+        },
+        /** @type {String|null} */
+        _repoUrl: String,
+      };
+    }
 
     _repoChanged(repoName) {
       if (!repoName) {
@@ -36,6 +40,8 @@
         return;
       }
       this._repoUrl = Gerrit.Nav.getUrlForRepo(repoName);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoHeader.is, GrRepoHeader);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html
index 266818e..85eb509 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-header</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.html b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.html
index fed1c12..8175849 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.html
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.html
@@ -27,7 +27,9 @@
 
 <dom-module id="gr-user-header">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="dashboard-header-styles">
       .name {
         display: inline-block;
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
index 6afc169..af8af3f 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
@@ -17,40 +17,44 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-user-header',
+  class GrUserHeader extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-user-header'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?String} */
-      userId: {
-        type: String,
-        observer: '_accountChanged',
-      },
+        userId: {
+          type: String,
+          observer: '_accountChanged',
+        },
 
-      showDashboardLink: {
-        type: Boolean,
-        value: false,
-      },
+        showDashboardLink: {
+          type: Boolean,
+          value: false,
+        },
 
-      loggedIn: {
-        type: Boolean,
-        value: false,
-      },
+        loggedIn: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * @type {?{name: ?, email: ?, registered_on: ?}}
        */
-      _accountDetails: {
-        type: Object,
-        value: null,
-      },
+        _accountDetails: {
+          type: Object,
+          value: null,
+        },
 
-      /** @type {?String} */
-      _status: {
-        type: String,
-        value: null,
-      },
-    },
+        /** @type {?String} */
+        _status: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
     _accountChanged(userId) {
       if (!userId) {
@@ -65,19 +69,19 @@
       this.$.restAPI.getAccountStatus(userId).then(status => {
         this._status = status;
       });
-    },
+    }
 
     _computeDisplayClass(status) {
       return status ? ' ' : 'hide';
-    },
+    }
 
     _computeDetail(accountDetails, name) {
       return accountDetails ? accountDetails[name] : '';
-    },
+    }
 
     _computeStatusClass(accountDetails) {
       return this._computeDetail(accountDetails, 'status') ? '' : 'hide';
-    },
+    }
 
     _computeDashboardUrl(accountDetails) {
       if (!accountDetails) { return null; }
@@ -85,11 +89,13 @@
       const email = accountDetails.email;
       if (!id && !email ) { return null; }
       return Gerrit.Nav.getUrlForUserDashboard(id ? id : email);
-    },
+    }
 
     _computeDashboardLinkClass(showDashboardLink, loggedIn) {
       return showDashboardLink && loggedIn ?
         'dashboardLink' : 'dashboardLink hide';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrUserHeader.is, GrUserHeader);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html
index e837a5b..9e04ecd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-user-header</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
index 4783509..0817762 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
@@ -125,6 +125,7 @@
                 link
                 title$="[[action.title]]"
                 has-tooltip="[[_computeHasTooltip(action.title)]]"
+                position-below="true"
                 data-action-key$="[[action.__key]]"
                 data-action-type$="[[action.__type]]"
                 data-label$="[[action.label]]"
@@ -145,6 +146,7 @@
                 link
                 title$="[[action.title]]"
                 has-tooltip="[[_computeHasTooltip(action.title)]]"
+                position-below="true"
                 data-action-key$="[[action.__key]]"
                 data-action-type$="[[action.__type]]"
                 data-label$="[[action.label]]"
@@ -191,12 +193,8 @@
           hidden></gr-confirm-cherrypick-dialog>
       <gr-confirm-cherrypick-conflict-dialog id="confirmCherrypickConflict"
           class="confirmDialog"
-          change-status="[[changeStatus]]"
-          commit-message="[[commitMessage]]"
-          commit-num="[[commitNum]]"
           on-confirm="_handleCherrypickConflictConfirm"
           on-cancel="_handleConfirmDialogCancel"
-          project="[[change.project]]"
           hidden></gr-confirm-cherrypick-conflict-dialog>
       <gr-confirm-move-dialog id="confirmMove"
           class="confirmDialog"
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index 0158627..2ce0d7d 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -192,9 +192,19 @@
   const AWAIT_CHANGE_ATTEMPTS = 5;
   const AWAIT_CHANGE_TIMEOUT_MS = 1000;
 
-  Polymer({
-    is: 'gr-change-actions',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrChangeActions extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-actions'; }
     /**
      * Fired when the change should be reloaded.
      *
@@ -219,7 +229,15 @@
      * @event show-error
      */
 
-    properties: {
+    constructor() {
+      super();
+      this.ActionType = ActionType;
+      this.ChangeActions = ChangeActions;
+      this.RevisionActions = RevisionActions;
+    }
+
+    static get properties() {
+      return {
       /**
        * @type {{
        *    _number: number,
@@ -229,217 +247,214 @@
        *    subject: string,
        *  }}
        */
-      change: Object,
-      actions: {
-        type: Object,
-        value() { return {}; },
-      },
-      primaryActionKeys: {
-        type: Array,
-        value() {
-          return [
-            RevisionActions.SUBMIT,
-          ];
+        change: Object,
+        actions: {
+          type: Object,
+          value() { return {}; },
         },
-      },
-      disableEdit: {
-        type: Boolean,
-        value: false,
-      },
-      _hasKnownChainState: {
-        type: Boolean,
-        value: false,
-      },
-      _hideQuickApproveAction: {
-        type: Boolean,
-        value: false,
-      },
-      changeNum: String,
-      changeStatus: String,
-      commitNum: String,
-      hasParent: {
-        type: Boolean,
-        observer: '_computeChainState',
-      },
-      latestPatchNum: String,
-      commitMessage: {
-        type: String,
-        value: '',
-      },
-      /** @type {?} */
-      revisionActions: {
-        type: Object,
-        notify: true,
-        value() { return {}; },
-      },
-      // If property binds directly to [[revisionActions.submit]] it is not
-      // updated when revisionActions doesn't contain submit action.
-      /** @type {?} */
-      _revisionSubmitAction: {
-        type: Object,
-        computed: '_getSubmitAction(revisionActions)',
-      },
-      // If property binds directly to [[revisionActions.rebase]] it is not
-      // updated when revisionActions doesn't contain rebase action.
-      /** @type {?} */
-      _revisionRebaseAction: {
-        type: Object,
-        computed: '_getRebaseAction(revisionActions)',
-      },
-      privateByDefault: String,
+        primaryActionKeys: {
+          type: Array,
+          value() {
+            return [
+              RevisionActions.SUBMIT,
+            ];
+          },
+        },
+        disableEdit: {
+          type: Boolean,
+          value: false,
+        },
+        _hasKnownChainState: {
+          type: Boolean,
+          value: false,
+        },
+        _hideQuickApproveAction: {
+          type: Boolean,
+          value: false,
+        },
+        changeNum: String,
+        changeStatus: String,
+        commitNum: String,
+        hasParent: {
+          type: Boolean,
+          observer: '_computeChainState',
+        },
+        latestPatchNum: String,
+        commitMessage: {
+          type: String,
+          value: '',
+        },
+        /** @type {?} */
+        revisionActions: {
+          type: Object,
+          notify: true,
+          value() { return {}; },
+        },
+        // If property binds directly to [[revisionActions.submit]] it is not
+        // updated when revisionActions doesn't contain submit action.
+        /** @type {?} */
+        _revisionSubmitAction: {
+          type: Object,
+          computed: '_getSubmitAction(revisionActions)',
+        },
+        // If property binds directly to [[revisionActions.rebase]] it is not
+        // updated when revisionActions doesn't contain rebase action.
+        /** @type {?} */
+        _revisionRebaseAction: {
+          type: Object,
+          computed: '_getRebaseAction(revisionActions)',
+        },
+        privateByDefault: String,
 
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _actionLoadingMessage: {
-        type: String,
-        value: '',
-      },
-      _allActionValues: {
-        type: Array,
-        computed: '_computeAllActions(actions.*, revisionActions.*,' +
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _actionLoadingMessage: {
+          type: String,
+          value: '',
+        },
+        _allActionValues: {
+          type: Array,
+          computed: '_computeAllActions(actions.*, revisionActions.*,' +
             'primaryActionKeys.*, _additionalActions.*, change, ' +
             '_actionPriorityOverrides.*)',
-      },
-      _topLevelActions: {
-        type: Array,
-        computed: '_computeTopLevelActions(_allActionValues.*, ' +
-            '_hiddenActions.*, _overflowActions.*)',
-        observer: '_filterPrimaryActions',
-      },
-      _topLevelPrimaryActions: Array,
-      _topLevelSecondaryActions: Array,
-      _menuActions: {
-        type: Array,
-        computed: '_computeMenuActions(_allActionValues.*, _hiddenActions.*, ' +
-            '_overflowActions.*)',
-      },
-      _overflowActions: {
-        type: Array,
-        value() {
-          const value = [
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.WIP,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.DELETE,
-            },
-            {
-              type: ActionType.REVISION,
-              key: RevisionActions.CHERRYPICK,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.MOVE,
-            },
-            {
-              type: ActionType.REVISION,
-              key: RevisionActions.DOWNLOAD,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.IGNORE,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.UNIGNORE,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.REVIEWED,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.UNREVIEWED,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.PRIVATE,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.PRIVATE_DELETE,
-            },
-            {
-              type: ActionType.CHANGE,
-              key: ChangeActions.FOLLOW_UP,
-            },
-          ];
-          return value;
         },
-      },
-      _actionPriorityOverrides: {
-        type: Array,
-        value() { return []; },
-      },
-      _additionalActions: {
-        type: Array,
-        value() { return []; },
-      },
-      _hiddenActions: {
-        type: Array,
-        value() { return []; },
-      },
-      _disabledMenuActions: {
-        type: Array,
-        value() { return []; },
-      },
-      // editPatchsetLoaded == "does the current selected patch range have
-      // 'edit' as one of either basePatchNum or patchNum".
-      editPatchsetLoaded: {
-        type: Boolean,
-        value: false,
-      },
-      // editMode == "is edit mode enabled in the file list".
-      editMode: {
-        type: Boolean,
-        value: false,
-      },
-      editBasedOnCurrentPatchSet: {
-        type: Boolean,
-        value: true,
-      },
-    },
+        _topLevelActions: {
+          type: Array,
+          computed: '_computeTopLevelActions(_allActionValues.*, ' +
+            '_hiddenActions.*, _overflowActions.*)',
+          observer: '_filterPrimaryActions',
+        },
+        _topLevelPrimaryActions: Array,
+        _topLevelSecondaryActions: Array,
+        _menuActions: {
+          type: Array,
+          computed: '_computeMenuActions(_allActionValues.*, ' +
+            '_hiddenActions.*, _overflowActions.*)',
+        },
+        _overflowActions: {
+          type: Array,
+          value() {
+            const value = [
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.WIP,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.DELETE,
+              },
+              {
+                type: ActionType.REVISION,
+                key: RevisionActions.CHERRYPICK,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.MOVE,
+              },
+              {
+                type: ActionType.REVISION,
+                key: RevisionActions.DOWNLOAD,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.IGNORE,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.UNIGNORE,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.REVIEWED,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.UNREVIEWED,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.PRIVATE,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.PRIVATE_DELETE,
+              },
+              {
+                type: ActionType.CHANGE,
+                key: ChangeActions.FOLLOW_UP,
+              },
+            ];
+            return value;
+          },
+        },
+        _actionPriorityOverrides: {
+          type: Array,
+          value() { return []; },
+        },
+        _additionalActions: {
+          type: Array,
+          value() { return []; },
+        },
+        _hiddenActions: {
+          type: Array,
+          value() { return []; },
+        },
+        _disabledMenuActions: {
+          type: Array,
+          value() { return []; },
+        },
+        // editPatchsetLoaded == "does the current selected patch range have
+        // 'edit' as one of either basePatchNum or patchNum".
+        editPatchsetLoaded: {
+          type: Boolean,
+          value: false,
+        },
+        // editMode == "is edit mode enabled in the file list".
+        editMode: {
+          type: Boolean,
+          value: false,
+        },
+        editBasedOnCurrentPatchSet: {
+          type: Boolean,
+          value: true,
+        },
+      };
+    }
 
-    ActionType,
-    ChangeActions,
-    RevisionActions,
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
-
-    observers: [
-      '_actionsChanged(actions.*, revisionActions.*, _additionalActions.*)',
-      '_changeChanged(change)',
-      '_editStatusChanged(editMode, editPatchsetLoaded, ' +
+    static get observers() {
+      return [
+        '_actionsChanged(actions.*, revisionActions.*, _additionalActions.*)',
+        '_changeChanged(change)',
+        '_editStatusChanged(editMode, editPatchsetLoaded, ' +
           'editBasedOnCurrentPatchSet, disableEdit, actions.*, change.*)',
-    ],
+      ];
+    }
 
-    listeners: {
-      'fullscreen-overlay-opened': '_handleHideBackgroundContent',
-      'fullscreen-overlay-closed': '_handleShowBackgroundContent',
-    },
+    created() {
+      super.created();
+      this.addEventListener('fullscreen-overlay-opened',
+          () => this._handleHideBackgroundContent());
+      this.addEventListener('fullscreen-overlay-closed',
+          () => this._handleShowBackgroundContent());
+    }
 
     ready() {
+      super.ready();
       this.$.jsAPI.addElement(this.$.jsAPI.Element.CHANGE_ACTIONS, this);
       this._handleLoadingComplete();
-    },
+    }
 
     _getSubmitAction(revisionActions) {
       return this._getRevisionAction(revisionActions, 'submit', null);
-    },
+    }
 
     _getRebaseAction(revisionActions) {
       return this._getRevisionAction(revisionActions, 'rebase',
           {rebaseOnCurrent: null}
       );
-    },
+    }
 
     _getRevisionAction(revisionActions, actionName, emptyActionValue) {
       if (!revisionActions) {
@@ -451,7 +466,7 @@
         return emptyActionValue;
       }
       return revisionActions[actionName];
-    },
+    }
 
     reload() {
       if (!this.changeNum || !this.latestPatchNum) {
@@ -469,11 +484,11 @@
         this._loading = false;
         throw err;
       });
-    },
+    }
 
     _handleLoadingComplete() {
       Gerrit.awaitPluginsLoaded().then(() => this._loading = false);
-    },
+    }
 
     _updateRebaseAction(revisionActions) {
       if (revisionActions && revisionActions.rebase) {
@@ -485,11 +500,11 @@
         this._parentIsCurrent = true;
       }
       return revisionActions;
-    },
+    }
 
     _changeChanged() {
       this.reload();
-    },
+    }
 
     addActionButton(type, label) {
       if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
@@ -504,7 +519,7 @@
       };
       this.push('_additionalActions', action);
       return action.__key;
-    },
+    }
 
     removeActionButton(key) {
       const idx = this._indexOfActionButtonWithKey(key);
@@ -512,7 +527,7 @@
         return;
       }
       this.splice('_additionalActions', idx, 1);
-    },
+    }
 
     setActionButtonProp(key, prop, value) {
       this.set([
@@ -520,7 +535,7 @@
         this._indexOfActionButtonWithKey(key),
         prop,
       ], value);
-    },
+    }
 
     setActionOverflow(type, key, overflow) {
       if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
@@ -537,7 +552,7 @@
       } else if (overflow) {
         this.push('_overflowActions', action);
       }
-    },
+    }
 
     setActionPriority(type, key, priority) {
       if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
@@ -556,7 +571,7 @@
       } else {
         this.push('_actionPriorityOverrides', action);
       }
-    },
+    }
 
     setActionHidden(type, key, hidden) {
       if (type !== ActionType.CHANGE && type !== ActionType.REVISION) {
@@ -569,7 +584,7 @@
       } else if (!hidden && idx !== -1) {
         this.splice('_hiddenActions', idx, 1);
       }
-    },
+    }
 
     getActionDetails(action) {
       if (this.revisionActions[action]) {
@@ -577,7 +592,7 @@
       } else if (this.actions[action]) {
         return this.actions[action];
       }
-    },
+    }
 
     _indexOfActionButtonWithKey(key) {
       for (let i = 0; i < this._additionalActions.length; i++) {
@@ -586,20 +601,20 @@
         }
       }
       return -1;
-    },
+    }
 
     _getRevisionActions() {
       return this.$.restAPI.getChangeRevisionActions(this.changeNum,
           this.latestPatchNum);
-    },
+    }
 
     _shouldHideActions(actions, loading) {
       return loading || !actions || !actions.base || !actions.base.length;
-    },
+    }
 
     _keyCount(changeRecord) {
       return Object.keys((changeRecord && changeRecord.base) || {}).length;
-    },
+    }
 
     _actionsChanged(actionsChangeRecord, revisionActionsChangeRecord,
         additionalActionsChangeRecord) {
@@ -626,7 +641,7 @@
           this.set('revisionActions.download', DOWNLOAD_ACTION);
         }
       }
-    },
+    }
 
     /**
        * @param {string=} actionName
@@ -638,7 +653,7 @@
         // see https://github.com/Polymer/polymer/issues/2631
         this.notifyPath('actions.' + actionName, false);
       }
-    },
+    }
 
     _editStatusChanged(editMode, editPatchsetLoaded,
         editBasedOnCurrentPatchSet, disableEdit) {
@@ -705,13 +720,13 @@
         // Remove edit button.
         this._deleteAndNotify('edit');
       }
-    },
+    }
 
     _getValuesFor(obj) {
       return Object.keys(obj).map(key => {
         return obj[key];
       });
-    },
+    }
 
     _getLabelStatus(label) {
       if (label.approved) {
@@ -723,7 +738,7 @@
       } else {
         return LabelStatus.NEED;
       }
-    },
+    }
 
     /**
      * Get highest score for last missing permitted label for current change.
@@ -771,7 +786,7 @@
         }
       }
       return null;
-    },
+    }
 
     hideQuickApproveAction() {
       this._topLevelSecondaryActions =
@@ -779,7 +794,7 @@
           return sa.key !== QUICK_APPROVE_ACTION.key;
         });
       this._hideQuickApproveAction = true;
-    },
+    }
 
     _getQuickApproveAction() {
       if (this._hideQuickApproveAction) {
@@ -798,7 +813,7 @@
       review.labels[approval.label] = approval.score;
       action.payload = review;
       return action;
-    },
+    }
 
     _getActionValues(actionsChangeRecord, primariesChangeRecord,
         additionalActionsChangeRecord, type) {
@@ -843,7 +858,7 @@
         return Object.assign({}, a);
       });
       return result.concat(additionalActions).concat(pluginActions);
-    },
+    }
 
     _populateActionUrl(action) {
       const patchNum =
@@ -851,7 +866,7 @@
       this.$.restAPI.getChangeActionURL(
           this.changeNum, patchNum, '/' + action.__key)
           .then(url => action.__url = url);
-    },
+    }
 
     /**
      * Given a change action, return a display label that uses the appropriate
@@ -867,7 +882,7 @@
       }
       // Otherwise, just map the name to sentence case.
       return this._toSentenceCase(action.label);
-    },
+    }
 
     /**
      * Capitalize the first letter and lowecase all others.
@@ -877,16 +892,16 @@
     _toSentenceCase(s) {
       if (!s.length) { return ''; }
       return s[0].toUpperCase() + s.slice(1).toLowerCase();
-    },
+    }
 
     _computeLoadingLabel(action) {
       return ActionLoadingLabels[action] || 'Working...';
-    },
+    }
 
     _canSubmitChange() {
       return this.$.jsAPI.canSubmitChange(this.change,
           this._getRevision(this.change, this.latestPatchNum));
-    },
+    }
 
     _getRevision(change, patchNum) {
       for (const rev of Object.values(change.revisions)) {
@@ -895,24 +910,24 @@
         }
       }
       return null;
-    },
+    }
 
     _modifyRevertMsg() {
       return this.$.jsAPI.modifyRevertMsg(this.change,
           this.$.confirmRevertDialog.message, this.commitMessage);
-    },
+    }
 
     showRevertDialog() {
       this.$.confirmRevertDialog.populateRevertMessage(
           this.commitMessage, this.change.current_revision);
       this.$.confirmRevertDialog.message = this._modifyRevertMsg();
       this._showActionDialog(this.$.confirmRevertDialog);
-    },
+    }
 
     _modifyRevertSubmissionMsg() {
       return this.$.jsAPI.modifyRevertSubmissionMsg(this.change,
           this.$.confirmRevertSubmissionDialog.message, this.commitMessage);
-    },
+    }
 
     showRevertSubmissionDialog() {
       this.$.confirmRevertSubmissionDialog.populateRevertSubmissionMessage(
@@ -920,7 +935,7 @@
       this.$.confirmRevertSubmissionDialog.message =
           this._modifyRevertSubmissionMsg();
       this._showActionDialog(this.$.confirmRevertSubmissionDialog);
-    },
+    }
 
     _handleActionTap(e) {
       e.preventDefault();
@@ -938,7 +953,7 @@
       }
       const type = el.getAttribute('data-action-type');
       this._handleAction(type, key);
-    },
+    }
 
     _handleOveflowItemTap(e) {
       e.preventDefault();
@@ -950,7 +965,7 @@
         return;
       }
       this._handleAction(e.detail.action.__type, e.detail.action.__key);
-    },
+    }
 
     _handleAction(type, key) {
       this.$.reporting.reportInteraction(`${type}-${key}`);
@@ -964,7 +979,7 @@
         default:
           this._fireAction(this._prependSlash(key), this.actions[key], false);
       }
-    },
+    }
 
     _handleChangeAction(key) {
       let action;
@@ -1015,7 +1030,7 @@
         default:
           this._fireAction(this._prependSlash(key), this.actions[key], false);
       }
-    },
+    }
 
     _handleRevisionAction(key) {
       switch (key) {
@@ -1037,11 +1052,11 @@
           this._fireAction(this._prependSlash(key),
               this.revisionActions[key], true);
       }
-    },
+    }
 
     _prependSlash(key) {
       return key === '/' ? key : `/${key}`;
-    },
+    }
 
     /**
      * _hasKnownChainState set to true true if hasParent is defined (can be
@@ -1049,25 +1064,25 @@
      */
     _computeChainState(hasParent) {
       this._hasKnownChainState = true;
-    },
+    }
 
     _calculateDisabled(action, hasKnownChainState) {
       if (action.__key === 'rebase' && hasKnownChainState === false) {
         return true;
       }
       return !action.enabled;
-    },
+    }
 
     _handleConfirmDialogCancel() {
       this._hideAllDialogs();
-    },
+    }
 
     _hideAllDialogs() {
       const dialogEls =
           Polymer.dom(this.root).querySelectorAll('.confirmDialog');
       for (const dialogEl of dialogEls) { dialogEl.hidden = true; }
       this.$.overlay.close();
-    },
+    }
 
     _handleRebaseConfirm(e) {
       const el = this.$.confirmRebase;
@@ -1075,15 +1090,15 @@
       this.$.overlay.close();
       el.hidden = true;
       this._fireAction('/rebase', this.revisionActions.rebase, true, payload);
-    },
+    }
 
     _handleCherrypickConfirm() {
       this._handleCherryPickRestApi(false);
-    },
+    }
 
     _handleCherrypickConflictConfirm() {
       this._handleCherryPickRestApi(true);
-    },
+    }
 
     _handleCherryPickRestApi(conflicts) {
       const el = this.$.confirmCherrypick;
@@ -1108,7 +1123,7 @@
             allow_conflicts: conflicts,
           }
       );
-    },
+    }
 
     _handleMoveConfirm() {
       const el = this.$.confirmMove;
@@ -1127,7 +1142,7 @@
             message: el.message,
           }
       );
-    },
+    }
 
     _handleRevertDialogConfirm() {
       const el = this.$.confirmRevertDialog;
@@ -1135,7 +1150,7 @@
       el.hidden = true;
       this._fireAction('/revert', this.actions.revert, false,
           {message: el.message});
-    },
+    }
 
     _handleRevertSubmissionDialogConfirm() {
       const el = this.$.confirmRevertSubmissionDialog;
@@ -1143,7 +1158,7 @@
       el.hidden = true;
       this._fireAction('/revert_submission', this.actions.revert_submission,
           false, {message: el.message});
-    },
+    }
 
     _handleAbandonDialogConfirm() {
       const el = this.$.confirmAbandonDialog;
@@ -1151,38 +1166,38 @@
       el.hidden = true;
       this._fireAction('/abandon', this.actions.abandon, false,
           {message: el.message});
-    },
+    }
 
     _handleCreateFollowUpChange() {
       this.$.createFollowUpChange.handleCreateChange();
       this._handleCloseCreateFollowUpChange();
-    },
+    }
 
     _handleCloseCreateFollowUpChange() {
       this.$.overlay.close();
-    },
+    }
 
     _handleDeleteConfirm() {
       this._fireAction('/', this.actions[ChangeActions.DELETE], false);
-    },
+    }
 
     _handleDeleteEditConfirm() {
       this._hideAllDialogs();
 
       this._fireAction('/edit', this.actions.deleteEdit, false);
-    },
+    }
 
     _handleSubmitConfirm() {
       if (!this._canSubmitChange()) { return; }
       this._hideAllDialogs();
       this._fireAction('/submit', this.revisionActions.submit, true);
-    },
+    }
 
     _getActionOverflowIndex(type, key) {
       return this._overflowActions.findIndex(action => {
         return action.type === type && action.key === key;
       });
-    },
+    }
 
     _setLoadingOnButtonWithKey(type, key) {
       this._actionLoadingMessage = this._computeLoadingLabel(key);
@@ -1205,7 +1220,7 @@
         buttonEl.removeAttribute('loading');
         buttonEl.disabled = false;
       }.bind(this);
-    },
+    }
 
     /**
      * @param {string} endpoint
@@ -1219,7 +1234,7 @@
 
       this._send(action.method, opt_payload, endpoint, revAction, cleanupFn,
           action).then(this._handleResponse.bind(this, action));
-    },
+    }
 
     _showActionDialog(dialog) {
       this._hideAllDialogs();
@@ -1230,7 +1245,7 @@
           dialog.resetFocus();
         }
       });
-    },
+    }
 
     // TODO(rmistry): Redo this after
     // https://bugs.chromium.org/p/gerrit/issues/detail?id=4671 is resolved.
@@ -1238,7 +1253,7 @@
       const labels = this.$.jsAPI.getLabelValuesPostRevert(this.change);
       if (!labels) { return Promise.resolve(); }
       return this.$.restAPI.saveChangeReview(newChangeId, 'current', {labels});
-    },
+    }
 
     _handleResponse(action, response) {
       if (!response) { return; }
@@ -1273,7 +1288,7 @@
             break;
         }
       });
-    },
+    }
 
     _handleResponseError(action, response, body) {
       if (action && action.__key === RevisionActions.CHERRYPICK) {
@@ -1290,7 +1305,7 @@
           throw Error(errText);
         }
       });
-    },
+    }
 
     /**
      * @param {string} method
@@ -1333,58 +1348,58 @@
                   return response;
                 });
           });
-    },
+    }
 
     _handleAbandonTap() {
       this._showActionDialog(this.$.confirmAbandonDialog);
-    },
+    }
 
     _handleCherrypickTap() {
       this.$.confirmCherrypick.branch = '';
       this._showActionDialog(this.$.confirmCherrypick);
-    },
+    }
 
     _handleMoveTap() {
       this.$.confirmMove.branch = '';
       this.$.confirmMove.message = '';
       this._showActionDialog(this.$.confirmMove);
-    },
+    }
 
     _handleDownloadTap() {
       this.fire('download-tap', null, {bubbles: false});
-    },
+    }
 
     _handleDeleteTap() {
       this._showActionDialog(this.$.confirmDeleteDialog);
-    },
+    }
 
     _handleDeleteEditTap() {
       this._showActionDialog(this.$.confirmDeleteEditDialog);
-    },
+    }
 
     _handleFollowUpTap() {
       this._showActionDialog(this.$.createFollowUpDialog);
-    },
+    }
 
     _handleWipTap() {
       this._fireAction('/wip', this.actions.wip, false);
-    },
+    }
 
     _handlePublishEditTap() {
       this._fireAction('/edit:publish', this.actions.publishEdit, false);
-    },
+    }
 
     _handleRebaseEditTap() {
       this._fireAction('/edit:rebase', this.actions.rebaseEdit, false);
-    },
+    }
 
     _handleHideBackgroundContent() {
       this.$.mainContent.classList.add('overlayOpen');
-    },
+    }
 
     _handleShowBackgroundContent() {
       this.$.mainContent.classList.remove('overlayOpen');
-    },
+    }
 
     /**
      * Merge sources of change actions into a single ordered array of action
@@ -1427,7 +1442,7 @@
             }
             return action;
           });
-    },
+    }
 
     _getActionPriority(action) {
       if (action.__type && action.__key) {
@@ -1449,7 +1464,7 @@
         return ActionPriority.REVISION;
       }
       return ActionPriority.DEFAULT;
-    },
+    }
 
     /**
      * Sort comparator to define the order of change actions.
@@ -1463,7 +1478,7 @@
       } else {
         return priorityDelta;
       }
-    },
+    }
 
     _computeTopLevelActions(actionRecord, hiddenActionsRecord) {
       const hiddenActions = hiddenActionsRecord.base || [];
@@ -1471,14 +1486,14 @@
         const overflow = this._getActionOverflowIndex(a.__type, a.__key) !== -1;
         return !(overflow || hiddenActions.includes(a.__key));
       });
-    },
+    }
 
     _filterPrimaryActions(_topLevelActions) {
       this._topLevelPrimaryActions = _topLevelActions.filter(action =>
         action.__primary);
       this._topLevelSecondaryActions = _topLevelActions.filter(action =>
         !action.__primary);
-    },
+    }
 
     _computeMenuActions(actionRecord, hiddenActionsRecord) {
       const hiddenActions = hiddenActionsRecord.base || [];
@@ -1495,7 +1510,7 @@
           tooltip: action.title,
         };
       });
-    },
+    }
 
     /**
      * Occasionally, a change created by a change action is not yet knwon to the
@@ -1529,22 +1544,24 @@
         };
         check();
       });
-    },
+    }
 
     _handleEditTap() {
       this.dispatchEvent(new CustomEvent('edit-tap', {bubbles: false}));
-    },
+    }
 
     _handleStopEditTap() {
       this.dispatchEvent(new CustomEvent('stop-edit-tap', {bubbles: false}));
-    },
+    }
 
     _computeHasTooltip(title) {
       return !!title;
-    },
+    }
 
     _computeHasIcon(action) {
       return action.icon ? '' : 'hidden';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeActions.is, GrChangeActions);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
index 862b4eb..a10f028 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-actions</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
index b8bea9ca..8d85dce 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-metadata</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 80b321f..a5a5aa5 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -37,12 +37,15 @@
 <link rel="import" href="../gr-change-requirements/gr-change-requirements.html">
 <link rel="import" href="../gr-commit-info/gr-commit-info.html">
 <link rel="import" href="../gr-reviewer-list/gr-reviewer-list.html">
+<link rel="import" href="../../shared/gr-account-list/gr-account-list.html">
 <script src="../../../scripts/gr-display-name-utils/gr-display-name-utils.js"></script>
 <script src="../../../scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.js"></script>
 
 <dom-module id="gr-change-metadata">
   <template>
-    <style include="gr-change-metadata-shared-styles"></style>
+    <style include="gr-change-metadata-shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       :host {
         display: table;
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
index 310a1a6..e0d9676 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.js
@@ -48,105 +48,111 @@
     TRUSTED: 'TRUSTED',
   };
 
-  Polymer({
-    is: 'gr-change-metadata',
-
+  /**
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrChangeMetadata extends Polymer.mixinBehaviors( [
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-metadata'; }
     /**
      * Fired when the change topic is changed.
      *
      * @event topic-changed
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      change: Object,
-      labels: {
-        type: Object,
-        notify: true,
-      },
-      account: Object,
-      /** @type {?} */
-      revision: Object,
-      commitInfo: Object,
-      _mutable: {
-        type: Boolean,
-        computed: '_computeIsMutable(account)',
-      },
-      /** @type {?} */
-      serverConfig: Object,
-      parentIsCurrent: Boolean,
-      _notCurrentMessage: {
-        type: String,
-        value: NOT_CURRENT_MESSAGE,
-        readOnly: true,
-      },
-      _topicReadOnly: {
-        type: Boolean,
-        computed: '_computeTopicReadOnly(_mutable, change)',
-      },
-      _hashtagReadOnly: {
-        type: Boolean,
-        computed: '_computeHashtagReadOnly(_mutable, change)',
-      },
-      /**
+        change: Object,
+        labels: {
+          type: Object,
+          notify: true,
+        },
+        account: Object,
+        /** @type {?} */
+        revision: Object,
+        commitInfo: Object,
+        _mutable: {
+          type: Boolean,
+          computed: '_computeIsMutable(account)',
+        },
+        /** @type {?} */
+        serverConfig: Object,
+        parentIsCurrent: Boolean,
+        _notCurrentMessage: {
+          type: String,
+          value: NOT_CURRENT_MESSAGE,
+          readOnly: true,
+        },
+        _topicReadOnly: {
+          type: Boolean,
+          computed: '_computeTopicReadOnly(_mutable, change)',
+        },
+        _hashtagReadOnly: {
+          type: Boolean,
+          computed: '_computeHashtagReadOnly(_mutable, change)',
+        },
+        /**
        * @type {Gerrit.PushCertificateValidation}
        */
-      _pushCertificateValidation: {
-        type: Object,
-        computed: '_computePushCertificateValidation(serverConfig, change)',
-      },
-      _showRequirements: {
-        type: Boolean,
-        computed: '_computeShowRequirements(change)',
-      },
-
-      _assignee: Array,
-      _isWip: {
-        type: Boolean,
-        computed: '_computeIsWip(change)',
-      },
-      _newHashtag: String,
-
-      _settingTopic: {
-        type: Boolean,
-        value: false,
-      },
-
-      _currentParents: {
-        type: Array,
-        computed: '_computeParents(change)',
-      },
-
-      /** @type {?} */
-      _CHANGE_ROLE: {
-        type: Object,
-        readOnly: true,
-        value: {
-          OWNER: 'owner',
-          UPLOADER: 'uploader',
-          AUTHOR: 'author',
-          COMMITTER: 'committer',
+        _pushCertificateValidation: {
+          type: Object,
+          computed: '_computePushCertificateValidation(serverConfig, change)',
         },
-      },
-    },
+        _showRequirements: {
+          type: Boolean,
+          computed: '_computeShowRequirements(change)',
+        },
 
-    behaviors: [
-      Gerrit.RESTClientBehavior,
-    ],
+        _assignee: Array,
+        _isWip: {
+          type: Boolean,
+          computed: '_computeIsWip(change)',
+        },
+        _newHashtag: String,
 
-    observers: [
-      '_changeChanged(change)',
-      '_labelsChanged(change.labels)',
-      '_assigneeChanged(_assignee.*)',
-    ],
+        _settingTopic: {
+          type: Boolean,
+          value: false,
+        },
+
+        _currentParents: {
+          type: Array,
+          computed: '_computeParents(change)',
+        },
+
+        /** @type {?} */
+        _CHANGE_ROLE: {
+          type: Object,
+          readOnly: true,
+          value: {
+            OWNER: 'owner',
+            UPLOADER: 'uploader',
+            AUTHOR: 'author',
+            COMMITTER: 'committer',
+          },
+        },
+      };
+    }
+
+    static get observers() {
+      return [
+        '_changeChanged(change)',
+        '_labelsChanged(change.labels)',
+        '_assigneeChanged(_assignee.*)',
+      ];
+    }
 
     _labelsChanged(labels) {
       this.labels = Object.assign({}, labels) || null;
-    },
+    }
 
     _changeChanged(change) {
       this._assignee = change.assignee ? [change.assignee] : [];
-    },
+    }
 
     _assigneeChanged(assigneeRecord) {
       if (!this.change) { return; }
@@ -162,11 +168,11 @@
         this.set(['change', 'assignee'], undefined);
         this.$.restAPI.deleteAssignee(this.change._number);
       }
-    },
+    }
 
     _computeHideStrategy(change) {
       return !this.changeIsOpen(change);
-    },
+    }
 
     /**
      * @param {Object} commitInfo
@@ -184,15 +190,15 @@
             config: serverConfig,
           });
       return weblinks.length ? weblinks : null;
-    },
+    }
 
     _computeStrategy(change) {
       return SubmitTypeLabel[change.submit_type];
-    },
+    }
 
     _computeLabelNames(labels) {
       return Object.keys(labels).sort();
-    },
+    }
 
     _handleTopicChanged(e, topic) {
       const lastTopic = this.change.topic;
@@ -207,19 +213,19 @@
                   'topic-changed', {bubbles: true, composed: true}));
             }
           });
-    },
+    }
 
     _showAddTopic(changeRecord, settingTopic) {
       const hasTopic = !!changeRecord &&
           !!changeRecord.base && !!changeRecord.base.topic;
       return !hasTopic && !settingTopic;
-    },
+    }
 
     _showTopicChip(changeRecord, settingTopic) {
       const hasTopic = !!changeRecord &&
           !!changeRecord.base && !!changeRecord.base.topic;
       return hasTopic && !settingTopic;
-    },
+    }
 
     _handleHashtagChanged(e) {
       const lastHashtag = this.change.hashtag;
@@ -234,7 +240,7 @@
               'hashtag-changed', {bubbles: true, composed: true}));
         }
       });
-    },
+    }
 
     _computeTopicReadOnly(mutable, change) {
       return !mutable ||
@@ -242,7 +248,7 @@
           !change.actions ||
           !change.actions.topic ||
           !change.actions.topic.enabled;
-    },
+    }
 
     _computeHashtagReadOnly(mutable, change) {
       return !mutable ||
@@ -250,7 +256,7 @@
           !change.actions ||
           !change.actions.hashtags ||
           !change.actions.hashtags.enabled;
-    },
+    }
 
     _computeAssigneeReadOnly(mutable, change) {
       return !mutable ||
@@ -258,17 +264,17 @@
           !change.actions ||
           !change.actions.assignee ||
           !change.actions.assignee.enabled;
-    },
+    }
 
     _computeTopicPlaceholder(_topicReadOnly) {
       // Action items in Material Design are uppercase -- placeholder label text
       // is sentence case.
       return _topicReadOnly ? 'No topic' : 'ADD TOPIC';
-    },
+    }
 
     _computeHashtagPlaceholder(_hashtagReadOnly) {
       return _hashtagReadOnly ? '' : HASHTAG_ADD_MESSAGE;
-    },
+    }
 
     _computeShowRequirements(change) {
       if (change.status !== this.ChangeStatus.NEW) {
@@ -281,7 +287,7 @@
       const hasLabels = !!change.labels &&
           Object.keys(change.labels).length > 0;
       return hasRequirements || hasLabels || !!change.work_in_progress;
-    },
+    }
 
     /**
      * @return {?Gerrit.PushCertificateValidation} object representing data for
@@ -326,7 +332,7 @@
         default:
           throw new Error(`unknown certificate status: ${key.status}`);
       }
-    },
+    }
 
     _problems(msg, key) {
       if (!key || !key.problems || key.problems.length === 0) {
@@ -334,26 +340,26 @@
       }
 
       return [msg + ':'].concat(key.problems).join('\n');
-    },
+    }
 
     _computeProjectURL(project) {
       return Gerrit.Nav.getUrlForProjectChanges(project);
-    },
+    }
 
     _computeBranchURL(project, branch) {
       if (!this.change || !this.change.status) return '';
       return Gerrit.Nav.getUrlForBranch(branch, project,
           this.change.status == this.ChangeStatus.NEW ? 'open' :
             this.change.status.toLowerCase());
-    },
+    }
 
     _computeTopicURL(topic) {
       return Gerrit.Nav.getUrlForTopic(topic);
-    },
+    }
 
     _computeHashtagURL(hashtag) {
       return Gerrit.Nav.getUrlForHashtag(hashtag);
-    },
+    }
 
     _handleTopicRemoved(e) {
       const target = Polymer.dom(e).rootTarget;
@@ -367,7 +373,7 @@
         target.disabled = false;
         return;
       });
-    },
+    }
 
     _handleHashtagRemoved(e) {
       e.preventDefault();
@@ -382,15 +388,15 @@
             target.disabled = false;
             return;
           });
-    },
+    }
 
     _computeIsWip(change) {
       return !!change.work_in_progress;
-    },
+    }
 
     _computeShowRoleClass(change, role) {
       return this._getNonOwnerRole(change, role) ? '' : 'hideDisplay';
-    },
+    }
 
     /**
      * Get the user with the specified role on the change. Returns null if the
@@ -427,7 +433,7 @@
       }
 
       return null;
-    },
+    }
 
     _computeParents(change) {
       if (!change || !change.current_revision ||
@@ -436,11 +442,11 @@
         return undefined;
       }
       return change.revisions[change.current_revision].commit.parents;
-    },
+    }
 
     _computeParentsLabel(parents) {
       return parents && parents.length > 1 ? 'Parents' : 'Parent';
-    },
+    }
 
     _computeParentListClass(parents, parentIsCurrent) {
       // Undefined check for polymer 2
@@ -453,24 +459,26 @@
         parents && parents.length > 1 ? 'merge' : 'nonMerge',
         parentIsCurrent ? 'current' : 'notCurrent',
       ].join(' ');
-    },
+    }
 
     _computeIsMutable(account) {
       return !!Object.keys(account).length;
-    },
+    }
 
     editTopic() {
       if (this._topicReadOnly || this.change.topic) { return; }
       // Cannot use `this.$.ID` syntax because the element exists inside of a
       // dom-if.
       this.$$('.topicEditableLabel').open();
-    },
+    }
 
     _getReviewerSuggestionsProvider(change) {
       const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
           change._number, Gerrit.SUGGESTIONS_PROVIDERS_USERS_TYPES.ANY);
       provider.init();
       return provider;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeMetadata.is, GrChangeMetadata);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
index 6f06fc8..148d917 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-metadata</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.js b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.js
index dfdcd59..2e0332b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.js
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements.js
@@ -17,47 +17,54 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-change-requirements',
+  /**
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrChangeRequirements extends Polymer.mixinBehaviors( [
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-requirements'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      change: Object,
-      account: Object,
-      mutable: Boolean,
-      _requirements: {
-        type: Array,
-        computed: '_computeRequirements(change)',
-      },
-      _requiredLabels: {
-        type: Array,
-        value: () => [],
-      },
-      _optionalLabels: {
-        type: Array,
-        value: () => [],
-      },
-      _showWip: {
-        type: Boolean,
-        computed: '_computeShowWip(change)',
-      },
-      _showOptionalLabels: {
-        type: Boolean,
-        value: true,
-      },
-    },
+        change: Object,
+        account: Object,
+        mutable: Boolean,
+        _requirements: {
+          type: Array,
+          computed: '_computeRequirements(change)',
+        },
+        _requiredLabels: {
+          type: Array,
+          value: () => [],
+        },
+        _optionalLabels: {
+          type: Array,
+          value: () => [],
+        },
+        _showWip: {
+          type: Boolean,
+          computed: '_computeShowWip(change)',
+        },
+        _showOptionalLabels: {
+          type: Boolean,
+          value: true,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.RESTClientBehavior,
-    ],
-
-    observers: [
-      '_computeLabels(change.labels.*)',
-    ],
+    static get observers() {
+      return [
+        '_computeLabels(change.labels.*)',
+      ];
+    }
 
     _computeShowWip(change) {
       return change.work_in_progress;
-    },
+    }
 
     _computeRequirements(change) {
       const _requirements = [];
@@ -78,15 +85,15 @@
       }
 
       return _requirements;
-    },
+    }
 
     _computeRequirementClass(requirementStatus) {
       return requirementStatus ? 'approved' : '';
-    },
+    }
 
     _computeRequirementIcon(requirementStatus) {
       return requirementStatus ? 'gr-icons:check' : 'gr-icons:hourglass';
-    },
+    }
 
     _computeLabels(labelsRecord) {
       const labels = labelsRecord.base;
@@ -103,7 +110,7 @@
 
         this.push(path, {label, icon, style, labelInfo});
       }
-    },
+    }
 
     /**
      * @param {Object} labelInfo
@@ -114,7 +121,7 @@
       if (labelInfo.approved) { return 'gr-icons:check'; }
       if (labelInfo.rejected) { return 'gr-icons:close'; }
       return 'gr-icons:hourglass';
-    },
+    }
 
     /**
      * @param {Object} labelInfo
@@ -123,28 +130,30 @@
       if (labelInfo.approved) { return 'approved'; }
       if (labelInfo.rejected) { return 'rejected'; }
       return '';
-    },
+    }
 
     _computeShowOptional(optionalFieldsRecord) {
       return optionalFieldsRecord.base.length ? '' : 'hidden';
-    },
+    }
 
     _computeLabelValue(value) {
       return (value > 0 ? '+' : '') + value;
-    },
+    }
 
     _computeShowHideIcon(showOptionalLabels) {
       return showOptionalLabels ?
         'gr-icons:expand-less' :
         'gr-icons:expand-more';
-    },
+    }
 
     _computeSectionClass(show) {
       return show ? '' : 'hidden';
-    },
+    }
 
     _handleShowHide(e) {
       this._showOptionalLabels = !this._showOptionalLabels;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeRequirements.is, GrChangeRequirements);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html
index 2ceac39..242fe2c 100644
--- a/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-requirements/gr-change-requirements_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-requirements</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 45df471..b86213a 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -408,8 +408,6 @@
               change-status="[[_change.status]]"
               commit-num="[[_commitInfo.commit]]"
               latest-patch-num="[[computeLatestPatchNum(_allPatchSets)]]"
-              reply-disabled="[[_replyDisabled]]"
-              reply-button-label="[[_replyButtonLabel]]"
               commit-message="[[_latestCommitMessage]]"
               edit-patchset-loaded="[[hasEditPatchsetLoaded(_patchRange.*)]]"
               edit-mode="[[_editMode]]"
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index ff63a32..5de378b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -63,9 +63,21 @@
   const CHANGE_RELOAD_TIMING_LABEL = 'ChangeReloaded';
   const SEND_REPLY_TIMING_LABEL = 'SendReply';
 
-  Polymer({
-    is: 'gr-change-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrChangeView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-view'; }
     /**
      * Fired when the title of the page should change.
      *
@@ -84,230 +96,215 @@
      * @event show-auth-required
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
-      /** @type {?} */
-      viewState: {
-        type: Object,
-        notify: true,
-        value() { return {}; },
-        observer: '_viewStateChanged',
-      },
-      backPage: String,
-      hasParent: Boolean,
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      disableEdit: {
-        type: Boolean,
-        value: false,
-      },
-      disableDiffPrefs: {
-        type: Boolean,
-        value: false,
-      },
-      _diffPrefsDisabled: {
-        type: Boolean,
-        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
-      },
-      _commentThreads: Array,
-      /** @type {?} */
-      _serverConfig: {
-        type: Object,
-        observer: '_startUpdateCheckTimer',
-      },
-      _diffPrefs: Object,
-      _numFilesShown: {
-        type: Number,
-        value: DEFAULT_NUM_FILES_SHOWN,
-        observer: '_numFilesShownChanged',
-      },
-      _account: {
-        type: Object,
-        value: {},
-      },
-      _prefs: Object,
-      /** @type {?} */
-      _changeComments: Object,
-      _canStartReview: {
-        type: Boolean,
-        computed: '_computeCanStartReview(_change)',
-      },
-      _comments: Object,
-      /** @type {?} */
-      _change: {
-        type: Object,
-        observer: '_changeChanged',
-      },
-      _revisionInfo: {
-        type: Object,
-        computed: '_getRevisionInfo(_change)',
-      },
-      /** @type {?} */
-      _commitInfo: Object,
-      _currentRevision: {
-        type: Object,
-        computed: '_computeCurrentRevision(_change.current_revision, ' +
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
+        /** @type {?} */
+        viewState: {
+          type: Object,
+          notify: true,
+          value() { return {}; },
+          observer: '_viewStateChanged',
+        },
+        backPage: String,
+        hasParent: Boolean,
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        disableEdit: {
+          type: Boolean,
+          value: false,
+        },
+        disableDiffPrefs: {
+          type: Boolean,
+          value: false,
+        },
+        _diffPrefsDisabled: {
+          type: Boolean,
+          computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
+        },
+        _commentThreads: Array,
+        /** @type {?} */
+        _serverConfig: {
+          type: Object,
+          observer: '_startUpdateCheckTimer',
+        },
+        _diffPrefs: Object,
+        _numFilesShown: {
+          type: Number,
+          value: DEFAULT_NUM_FILES_SHOWN,
+          observer: '_numFilesShownChanged',
+        },
+        _account: {
+          type: Object,
+          value: {},
+        },
+        _prefs: Object,
+        /** @type {?} */
+        _changeComments: Object,
+        _canStartReview: {
+          type: Boolean,
+          computed: '_computeCanStartReview(_change)',
+        },
+        _comments: Object,
+        /** @type {?} */
+        _change: {
+          type: Object,
+          observer: '_changeChanged',
+        },
+        _revisionInfo: {
+          type: Object,
+          computed: '_getRevisionInfo(_change)',
+        },
+        /** @type {?} */
+        _commitInfo: Object,
+        _currentRevision: {
+          type: Object,
+          computed: '_computeCurrentRevision(_change.current_revision, ' +
             '_change.revisions)',
-      },
-      _files: Object,
-      _changeNum: String,
-      _diffDrafts: {
-        type: Object,
-        value() { return {}; },
-      },
-      _editingCommitMessage: {
-        type: Boolean,
-        value: false,
-      },
-      _hideEditCommitMessage: {
-        type: Boolean,
-        computed: '_computeHideEditCommitMessage(_loggedIn, ' +
+        },
+        _files: Object,
+        _changeNum: String,
+        _diffDrafts: {
+          type: Object,
+          value() { return {}; },
+        },
+        _editingCommitMessage: {
+          type: Boolean,
+          value: false,
+        },
+        _hideEditCommitMessage: {
+          type: Boolean,
+          computed: '_computeHideEditCommitMessage(_loggedIn, ' +
             '_editingCommitMessage, _change, _editMode)',
-      },
-      _diffAgainst: String,
-      /** @type {?string} */
-      _latestCommitMessage: {
-        type: String,
-        value: '',
-      },
-      _lineHeight: Number,
-      _changeIdCommitMessageError: {
-        type: String,
-        computed:
+        },
+        _diffAgainst: String,
+        /** @type {?string} */
+        _latestCommitMessage: {
+          type: String,
+          value: '',
+        },
+        _lineHeight: Number,
+        _changeIdCommitMessageError: {
+          type: String,
+          computed:
           '_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
-      },
-      /** @type {?} */
-      _patchRange: {
-        type: Object,
-      },
-      _filesExpanded: String,
-      _basePatchNum: String,
-      _selectedRevision: Object,
-      _currentRevisionActions: Object,
-      _allPatchSets: {
-        type: Array,
-        computed: 'computeAllPatchSets(_change, _change.revisions.*)',
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-      _loading: Boolean,
-      /** @type {?} */
-      _projectConfig: Object,
-      _rebaseOnCurrent: Boolean,
-      _replyButtonLabel: {
-        type: String,
-        value: 'Reply',
-        computed: '_computeReplyButtonLabel(_diffDrafts.*, _canStartReview)',
-      },
-      _selectedPatchSet: String,
-      _shownFileCount: Number,
-      _initialLoadComplete: {
-        type: Boolean,
-        value: false,
-      },
-      _replyDisabled: {
-        type: Boolean,
-        value: true,
-        computed: '_computeReplyDisabled(_serverConfig)',
-      },
-      _changeStatus: {
-        type: String,
-        computed: 'changeStatusString(_change)',
-      },
-      _changeStatuses: {
-        type: String,
-        computed:
+        },
+        /** @type {?} */
+        _patchRange: {
+          type: Object,
+        },
+        _filesExpanded: String,
+        _basePatchNum: String,
+        _selectedRevision: Object,
+        _currentRevisionActions: Object,
+        _allPatchSets: {
+          type: Array,
+          computed: 'computeAllPatchSets(_change, _change.revisions.*)',
+        },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+        _loading: Boolean,
+        /** @type {?} */
+        _projectConfig: Object,
+        _rebaseOnCurrent: Boolean,
+        _replyButtonLabel: {
+          type: String,
+          value: 'Reply',
+          computed: '_computeReplyButtonLabel(_diffDrafts.*, _canStartReview)',
+        },
+        _selectedPatchSet: String,
+        _shownFileCount: Number,
+        _initialLoadComplete: {
+          type: Boolean,
+          value: false,
+        },
+        _replyDisabled: {
+          type: Boolean,
+          value: true,
+          computed: '_computeReplyDisabled(_serverConfig)',
+        },
+        _changeStatus: {
+          type: String,
+          computed: 'changeStatusString(_change)',
+        },
+        _changeStatuses: {
+          type: String,
+          computed:
           '_computeChangeStatusChips(_change, _mergeable, _submitEnabled)',
-      },
-      _commitCollapsed: {
-        type: Boolean,
-        value: true,
-      },
-      _relatedChangesCollapsed: {
-        type: Boolean,
-        value: true,
-      },
-      /** @type {?number} */
-      _updateCheckTimerHandle: Number,
-      _editMode: {
-        type: Boolean,
-        computed: '_computeEditMode(_patchRange.*, params.*)',
-      },
-      _showRelatedToggle: {
-        type: Boolean,
-        value: false,
-        observer: '_updateToggleContainerClass',
-      },
-      _parentIsCurrent: Boolean,
-      _submitEnabled: {
-        type: Boolean,
-        computed: '_isSubmitEnabled(_currentRevisionActions)',
-      },
+        },
+        _commitCollapsed: {
+          type: Boolean,
+          value: true,
+        },
+        _relatedChangesCollapsed: {
+          type: Boolean,
+          value: true,
+        },
+        /** @type {?number} */
+        _updateCheckTimerHandle: Number,
+        _editMode: {
+          type: Boolean,
+          computed: '_computeEditMode(_patchRange.*, params.*)',
+        },
+        _showRelatedToggle: {
+          type: Boolean,
+          value: false,
+          observer: '_updateToggleContainerClass',
+        },
+        _parentIsCurrent: Boolean,
+        _submitEnabled: {
+          type: Boolean,
+          computed: '_isSubmitEnabled(_currentRevisionActions)',
+        },
 
-      /** @type {?} */
-      _mergeable: {
-        type: Boolean,
-        value: undefined,
-      },
-      _showMessagesView: {
-        type: Boolean,
-        value: true,
-      },
-      _showFileTabContent: {
-        type: Boolean,
-        value: true,
-      },
-      /** @type {Array<string>} */
-      _dynamicTabHeaderEndpoints: {
-        type: Array,
-      },
-      _showPrimaryTabs: {
-        type: Boolean,
-        computed: '_computeShowPrimaryTabs(_dynamicTabHeaderEndpoints)',
-      },
-      /** @type {Array<string>} */
-      _dynamicTabContentEndpoints: {
-        type: Array,
-      },
-      _selectedFilesTabPluginEndpoint: {
-        type: String,
-      },
-    },
+        /** @type {?} */
+        _mergeable: {
+          type: Boolean,
+          value: undefined,
+        },
+        _showMessagesView: {
+          type: Boolean,
+          value: true,
+        },
+        _showFileTabContent: {
+          type: Boolean,
+          value: true,
+        },
+        /** @type {Array<string>} */
+        _dynamicTabHeaderEndpoints: {
+          type: Array,
+        },
+        _showPrimaryTabs: {
+          type: Boolean,
+          computed: '_computeShowPrimaryTabs(_dynamicTabHeaderEndpoints)',
+        },
+        /** @type {Array<string>} */
+        _dynamicTabContentEndpoints: {
+          type: Array,
+        },
+        _selectedFilesTabPluginEndpoint: {
+          type: String,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
-
-    listeners: {
-      'topic-changed': '_handleTopicChanged',
-      // When an overlay is opened in a mobile viewport, the overlay has a full
-      // screen view. When it has a full screen view, we do not want the
-      // background to be scrollable. This will eliminate background scroll by
-      // hiding most of the contents on the screen upon opening, and showing
-      // again upon closing.
-      'fullscreen-overlay-opened': '_handleHideBackgroundContent',
-      'fullscreen-overlay-closed': '_handleShowBackgroundContent',
-      'diff-comments-modified': '_handleReloadCommentThreads',
-    },
-
-    observers: [
-      '_labelsChanged(_change.labels.*)',
-      '_paramsAndChangeChanged(params, _change)',
-      '_patchNumChanged(_patchRange.patchNum)',
-    ],
+    static get observers() {
+      return [
+        '_labelsChanged(_change.labels.*)',
+        '_paramsAndChangeChanged(params, _change)',
+        '_patchNumChanged(_patchRange.patchNum)',
+      ];
+    }
 
     keyboardShortcuts() {
       return {
@@ -325,9 +322,32 @@
         [this.Shortcut.OPEN_DIFF_PREFS]: '_handleOpenDiffPrefsShortcut',
         [this.Shortcut.EDIT_TOPIC]: '_handleEditTopic',
       };
-    },
+    }
+
+    created() {
+      super.created();
+
+      this.addEventListener('topic-changed',
+          () => this._handleTopicChanged());
+
+      this.addEventListener(
+          // When an overlay is opened in a mobile viewport, the overlay has a full
+          // screen view. When it has a full screen view, we do not want the
+          // background to be scrollable. This will eliminate background scroll by
+          // hiding most of the contents on the screen upon opening, and showing
+          // again upon closing.
+          'fullscreen-overlay-opened',
+          () => this._handleHideBackgroundContent());
+
+      this.addEventListener('fullscreen-overlay-closed',
+          () => this._handleShowBackgroundContent());
+
+      this.addEventListener('diff-comments-modified',
+          () => this._handleReloadCommentThreads());
+    }
 
     attached() {
+      super.attached();
       this._getServerConfig().then(config => {
         this._serverConfig = config;
       });
@@ -363,24 +383,25 @@
           this._handleCommitMessageCancel.bind(this));
       this.listen(window, 'scroll', '_handleScroll');
       this.listen(document, 'visibilitychange', '_handleVisibilityChange');
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'scroll', '_handleScroll');
       this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');
 
       if (this._updateCheckTimerHandle) {
         this._cancelUpdateCheckTimer();
       }
-    },
+    }
 
     get messagesList() {
       return this.$$('gr-messages-list');
-    },
+    }
 
     get threadList() {
       return this.$$('gr-thread-list');
-    },
+    }
 
     /**
      * @param {boolean=} opt_reset
@@ -397,7 +418,7 @@
           this.set('viewState.diffMode', 'SIDE_BY_SIDE');
         }
       });
-    },
+    }
 
     _handleToggleDiffMode(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -409,11 +430,11 @@
       } else {
         this.$.fileListHeader.setDiffViewMode(DiffViewMode.SIDE_BY_SIDE);
       }
-    },
+    }
 
     _handleCommentTabChange() {
       this._showMessagesView = this.$.commentTabs.selected === 0;
-    },
+    }
 
     _handleFileTabChange(e) {
       const selectedIndex = this.$$('#primaryTabs').selected;
@@ -429,7 +450,7 @@
         this.$.reporting.reportInteraction('tab-changed',
             `tabname: ${tabName}, source: ${source}`);
       }
-    },
+    }
 
     _handleShowTab(e) {
       const idx = this._dynamicTabContentEndpoints.indexOf(e.detail.tab);
@@ -440,12 +461,12 @@
       this.$$('#primaryTabs').selected = idx + 1;
       this.$$('#primaryTabs').scrollIntoView();
       this.$.reporting.reportInteraction('show-tab', e.detail.tab);
-    },
+    }
 
     _handleEditCommitMessage(e) {
       this._editingCommitMessage = true;
       this.$.commitMessageEditor.focusTextarea();
-    },
+    }
 
     _handleCommitMessageSave(e) {
       // Trim trailing whitespace from each line.
@@ -466,15 +487,15 @@
       }).catch(err => {
         this.$.commitMessageEditor.disabled = false;
       });
-    },
+    }
 
     _reloadWindow() {
       window.location.reload();
-    },
+    }
 
     _handleCommitMessageCancel(e) {
       this._editingCommitMessage = false;
-    },
+    }
 
     _computeChangeStatusChips(change, mergeable, submitEnabled) {
       // Polymer 2: check for undefined
@@ -498,7 +519,7 @@
         submitEnabled: !!submitEnabled,
       };
       return this.changeStatuses(change, options);
-    },
+    }
 
     _computeHideEditCommitMessage(loggedIn, editing, change, editMode) {
       if (!loggedIn || editing ||
@@ -508,7 +529,7 @@
       }
 
       return false;
-    },
+    }
 
     _handleReloadCommentThreads() {
       // Get any new drafts that have been saved in the diff view and show
@@ -518,7 +539,7 @@
             .map(c => Object.assign({}, c));
         Polymer.dom.flush();
       });
-    },
+    }
 
     _handleReloadDiffComments(e) {
       // Keeps the file list counts updated.
@@ -529,7 +550,7 @@
             e.detail.path);
         Polymer.dom.flush();
       });
-    },
+    }
 
     _computeTotalCommentCounts(unresolvedCount, changeComments) {
       if (!changeComments) return undefined;
@@ -543,7 +564,7 @@
           // Add a comma and space if both unresolved and draft comments exist.
           (unresolvedString && draftString ? ', ' : '') +
           draftString;
-    },
+    }
 
     _handleCommentSave(e) {
       const draft = e.detail.comment;
@@ -575,7 +596,7 @@
         return (c1.line || -1) - (c2.line || -1);
       });
       this._diffDrafts = diffDrafts;
-    },
+    }
 
     _handleCommentDiscard(e) {
       const draft = e.detail.comment;
@@ -609,16 +630,16 @@
         delete diffDrafts[draft.path];
       }
       this._diffDrafts = diffDrafts;
-    },
+    }
 
     _handleReplyTap(e) {
       e.preventDefault();
       this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
-    },
+    }
 
     _handleOpenDiffPrefs() {
       this.$.fileList.openDiffPrefs();
-    },
+    }
 
     _handleOpenIncludedInDialog() {
       this.$.includedInDialog.loadData().then(() => {
@@ -626,11 +647,11 @@
         this.$.includedInOverlay.refit();
       });
       this.$.includedInOverlay.open();
-    },
+    }
 
     _handleIncludedInDialogClose(e) {
       this.$.includedInOverlay.close();
-    },
+    }
 
     _handleOpenDownloadDialog() {
       this.$.downloadOverlay.open().then(() => {
@@ -638,19 +659,19 @@
             .setFocusStops(this.$.downloadDialog.getFocusStops());
         this.$.downloadDialog.focus();
       });
-    },
+    }
 
     _handleDownloadDialogClose(e) {
       this.$.downloadOverlay.close();
-    },
+    }
 
     _handleOpenUploadHelpDialog(e) {
       this.$.uploadHelpOverlay.open();
-    },
+    }
 
     _handleCloseUploadHelpDialog(e) {
       this.$.uploadHelpOverlay.close();
-    },
+    }
 
     _handleMessageReply(e) {
       const msg = e.detail.message.message;
@@ -658,33 +679,33 @@
           line => { return '> ' + line; }).join('\n') + '\n\n';
       this.$.replyDialog.quote = quoteStr;
       this._openReplyDialog(this.$.replyDialog.FocusTarget.BODY);
-    },
+    }
 
     _handleHideBackgroundContent() {
       this.$.mainContent.classList.add('overlayOpen');
-    },
+    }
 
     _handleShowBackgroundContent() {
       this.$.mainContent.classList.remove('overlayOpen');
-    },
+    }
 
     _handleReplySent(e) {
       this.$.replyOverlay.close();
       this._reload().then(() => {
         this.$.reporting.timeEnd(SEND_REPLY_TIMING_LABEL);
       });
-    },
+    }
 
     _handleReplyCancel(e) {
       this.$.replyOverlay.close();
-    },
+    }
 
     _handleReplyAutogrow(e) {
       // If the textarea resizes, we need to re-fit the overlay.
       this.debounce('reply-overlay-refit', () => {
         this.$.replyOverlay.refit();
       }, REPLY_REFIT_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _handleShowReplyDialog(e) {
       let target = this.$.replyDialog.FocusTarget.REVIEWERS;
@@ -692,25 +713,25 @@
         target = this.$.replyDialog.FocusTarget.CCS;
       }
       this._openReplyDialog(target);
-    },
+    }
 
     _handleScroll() {
       this.debounce('scroll', () => {
         this.viewState.scrollTop = document.body.scrollTop;
       }, 150);
-    },
+    }
 
     _setShownFiles(e) {
       this._shownFileCount = e.detail.length;
-    },
+    }
 
     _expandAllDiffs() {
       this.$.fileList.expandAllDiffs();
-    },
+    }
 
     _collapseAllDiffs() {
       this.$.fileList.collapseAllDiffs();
-    },
+    }
 
     _paramsChanged(value) {
       // Change the content of the comment tabs back to messages list, but
@@ -764,7 +785,7 @@
       this._reload(true).then(() => {
         this._performPostLoadTasks();
       });
-    },
+    }
 
     _sendShowChangeEvent() {
       this.$.jsAPI.handleEvent(this.$.jsAPI.EventType.SHOW_CHANGE, {
@@ -772,7 +793,7 @@
         patchNum: this._patchRange.patchNum,
         info: {mergeable: this._mergeable},
       });
-    },
+    }
 
     _setPrimaryTab() {
       // Selected has to be set after the paper-tabs are visible because
@@ -780,7 +801,7 @@
       this.$.commentTabs.selected = 0;
       const primaryTabs = this.$$('#primaryTabs');
       if (primaryTabs) primaryTabs.selected = 0;
-    },
+    }
 
     _performPostLoadTasks() {
       this._maybeShowReplyDialog();
@@ -799,7 +820,7 @@
         }
         this._initialLoadComplete = true;
       });
-    },
+    }
 
     _paramsAndChangeChanged(value, change) {
       // Polymer 2: check for undefined
@@ -815,16 +836,16 @@
           patchRangeState.patchNum !== this._patchRange.patchNum) {
         this._resetFileListViewState();
       }
-    },
+    }
 
     _viewStateChanged(viewState) {
       this._numFilesShown = viewState.numFilesShown ?
         viewState.numFilesShown : DEFAULT_NUM_FILES_SHOWN;
-    },
+    }
 
     _numFilesShownChanged(numFilesShown) {
       this.viewState.numFilesShown = numFilesShown;
-    },
+    }
 
     _handleMessageAnchorTap(e) {
       const hash = MSG_PREFIX + e.detail.id;
@@ -832,18 +853,18 @@
           this._patchRange.patchNum, this._patchRange.basePatchNum,
           this._editMode, hash);
       history.replaceState(null, '', url);
-    },
+    }
 
     _maybeScrollToMessage(hash) {
       if (hash.startsWith(MSG_PREFIX)) {
         this.messagesList.scrollToMessage(hash.substr(MSG_PREFIX.length));
       }
-    },
+    }
 
     _getLocationSearch() {
       // Not inlining to make it easier to test.
       return window.location.search;
-    },
+    }
 
     _getUrlParameter(param) {
       const pageURL = this._getLocationSearch().substring(1);
@@ -855,7 +876,7 @@
         }
       }
       return null;
-    },
+    }
 
     _maybeShowRevertDialog() {
       Gerrit.awaitPluginsLoaded()
@@ -871,7 +892,7 @@
               this.$.actions.showRevertDialog();
             }
           });
-    },
+    }
 
     _maybeShowReplyDialog() {
       this._getLoggedIn().then(loggedIn => {
@@ -885,7 +906,7 @@
           this.set('viewState.showReplyDialog', false);
         }
       });
-    },
+    }
 
     _resetFileListViewState() {
       this.set('viewState.selectedFileIndex', 0);
@@ -899,7 +920,7 @@
       }
       this.set('viewState.changeNum', this._changeNum);
       this.set('viewState.patchRange', this._patchRange);
-    },
+    }
 
     _changeChanged(change) {
       if (!change || !this._patchRange || !this._allPatchSets) { return; }
@@ -915,7 +936,7 @@
 
       const title = change.subject + ' (' + change.change_id.substr(0, 9) + ')';
       this.fire('title-change', {title});
-    },
+    }
 
     /**
      * Gets base patch number, if it is a parent try and decide from
@@ -947,19 +968,19 @@
       }
 
       return 'PARENT';
-    },
+    }
 
     _computeShowPrimaryTabs(dynamicTabHeaderEndpoints) {
       return dynamicTabHeaderEndpoints && dynamicTabHeaderEndpoints.length > 0;
-    },
+    }
 
     _computeChangeUrl(change) {
       return Gerrit.Nav.getUrlForChange(change);
-    },
+    }
 
     _computeShowCommitInfo(changeStatus, current_revision) {
       return changeStatus === 'Merged' && current_revision;
-    },
+    }
 
     _computeMergedCommitInfo(current_revision, revisions) {
       const rev = revisions[current_revision];
@@ -968,11 +989,11 @@
       // in <gr-commit-info>. @see Issue 5337
       if (!rev.commit.commit) { rev.commit.commit = current_revision; }
       return rev.commit;
-    },
+    }
 
     _computeChangeIdClass(displayChangeId) {
       return displayChangeId === CHANGE_ID_ERROR.MISMATCH ? 'warning' : '';
-    },
+    }
 
     _computeTitleAttributeWarning(displayChangeId) {
       if (displayChangeId === CHANGE_ID_ERROR.MISMATCH) {
@@ -980,7 +1001,7 @@
       } else if (displayChangeId === CHANGE_ID_ERROR.MISSING) {
         return 'No Change-Id in commit message';
       }
-    },
+    }
 
     _computeChangeIdCommitMessageError(commitMessage, change) {
       // Polymer 2: check for undefined
@@ -1010,11 +1031,11 @@
       }
       // There is no change-id in the commit message.
       return CHANGE_ID_ERROR.MISSING;
-    },
+    }
 
     _computeLabelNames(labels) {
       return Object.keys(labels).sort();
-    },
+    }
 
     _computeLabelValues(labelName, labels) {
       const result = [];
@@ -1039,7 +1060,7 @@
         }
       }
       return result;
-    },
+    }
 
     _computeReplyButtonLabel(changeRecord, canStartReview) {
       // Polymer 2: check for undefined
@@ -1061,7 +1082,7 @@
         label += ' (' + draftCount + ')';
       }
       return label;
-    },
+    }
 
     _handleOpenReplyDialog(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1077,7 +1098,7 @@
         e.preventDefault();
         this._openReplyDialog(this.$.replyDialog.FocusTarget.ANY);
       });
-    },
+    }
 
     _handleOpenDownloadDialogShortcut(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1085,7 +1106,7 @@
 
       e.preventDefault();
       this.$.downloadOverlay.open();
-    },
+    }
 
     _handleEditTopic(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1093,13 +1114,13 @@
 
       e.preventDefault();
       this.$.metadata.editTopic();
-    },
+    }
 
     _handleRefreshChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
       e.preventDefault();
       Gerrit.Nav.navigateToChange(this._change);
-    },
+    }
 
     _handleToggleChangeStar(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1107,7 +1128,7 @@
 
       e.preventDefault();
       this.$.changeStar.toggleStar();
-    },
+    }
 
     _handleUpToDashboard(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1115,7 +1136,7 @@
 
       e.preventDefault();
       this._determinePageBack();
-    },
+    }
 
     _handleExpandAllMessages(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1123,7 +1144,7 @@
 
       e.preventDefault();
       this.messagesList.handleExpandCollapse(true);
-    },
+    }
 
     _handleCollapseAllMessages(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1131,7 +1152,7 @@
 
       e.preventDefault();
       this.messagesList.handleExpandCollapse(false);
-    },
+    }
 
     _handleOpenDiffPrefsShortcut(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -1141,14 +1162,14 @@
 
       e.preventDefault();
       this.$.fileList.openDiffPrefs();
-    },
+    }
 
     _determinePageBack() {
       // Default backPage to root if user came to change view page
       // via an email link, etc.
       Gerrit.Nav.navigateToRelativeUrl(this.backPage ||
           Gerrit.Nav.getUrlForRoot());
-    },
+    }
 
     _handleLabelRemoved(splices, path) {
       for (const splice of splices) {
@@ -1163,7 +1184,7 @@
           }
         }
       }
-    },
+    }
 
     _labelsChanged(changeRecord) {
       if (!changeRecord) { return; }
@@ -1174,7 +1195,7 @@
       this.$.jsAPI.handleEvent(this.$.jsAPI.EventType.LABEL_CHANGE, {
         change: this._change,
       });
-    },
+    }
 
     /**
      * @param {string=} opt_section
@@ -1186,7 +1207,7 @@
         Polymer.dom.flush();
         this.$.replyOverlay.center();
       });
-    },
+    }
 
     _handleReloadChange(e) {
       return this._reload().then(() => {
@@ -1197,19 +1218,19 @@
           Gerrit.Nav.navigateToChange(this._change);
         }
       });
-    },
+    }
 
     _handleGetChangeDetailError(response) {
       this.fire('page-error', {response});
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getServerConfig() {
       return this.$.restAPI.getConfig();
-    },
+    }
 
     _getProjectConfig() {
       if (!this._change) return;
@@ -1217,18 +1238,18 @@
           config => {
             this._projectConfig = config;
           });
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     _prepareCommitMsgForLinkify(msg) {
       // TODO(wyatta) switch linkify sequence, see issue 5526.
       // This is a zero-with space. It is added to prevent the linkify library
       // from including R= or CC= as part of the email address.
       return msg.replace(REVIEWERS_REGEX, '$1=\u200B');
-    },
+    }
 
     /**
      * Utility function to make the necessary modifications to a change in the
@@ -1258,7 +1279,7 @@
         change.revisions[edit.commit.commit].actions =
             change.revisions[edit.base_revision].actions;
       }
-    },
+    }
 
     _getChangeDetail() {
       const detailCompletes = this.$.restAPI.getChangeDetail(
@@ -1312,16 +1333,16 @@
                       parseInt(this._patchRange.patchNum, 10));
             }
           });
-    },
+    }
 
     _isSubmitEnabled(revisionActions) {
       return !!(revisionActions && revisionActions.submit &&
         revisionActions.submit.enabled);
-    },
+    }
 
     _getEdit() {
       return this.$.restAPI.getChangeEdit(this._changeNum, true);
-    },
+    }
 
     _getLatestCommitMessage() {
       return this.$.restAPI.getChangeCommitInfo(this._changeNum,
@@ -1330,7 +1351,7 @@
         this._latestCommitMessage =
                     this._prepareCommitMsgForLinkify(commitInfo.message);
       });
-    },
+    }
 
     _getLatestRevisionSHA(change) {
       if (change.current_revision) {
@@ -1349,7 +1370,7 @@
         }
       }
       return latestRev;
-    },
+    }
 
     _getCommitInfo() {
       return this.$.restAPI.getChangeCommitInfo(
@@ -1357,13 +1378,13 @@
           commitInfo => {
             this._commitInfo = commitInfo;
           });
-    },
+    }
 
     _reloadDraftsWithCallback(e) {
       return this._reloadDrafts().then(() => {
         return e.detail.resolve();
       });
-    },
+    }
 
     /**
      * Fetches a new changeComment object, and data for all types of comments
@@ -1377,7 +1398,7 @@
             this._commentThreads = this._changeComments.getAllThreadsForChange()
                 .map(c => Object.assign({}, c));
           });
-    },
+    }
 
     /**
      * Fetches a new changeComment object, but only updated data for drafts is
@@ -1389,7 +1410,7 @@
             this._changeComments = comments;
             this._diffDrafts = Object.assign({}, this._changeComments.drafts);
           });
-    },
+    }
 
     /**
      * Reload the change.
@@ -1496,7 +1517,7 @@
       });
 
       return coreDataPromise;
-    },
+    }
 
     /**
      * Kicks off requests for resources that rely on the patch range
@@ -1507,7 +1528,7 @@
         this._getCommitInfo(),
         this.$.fileList.reload(),
       ]);
-    },
+    }
 
     _getMergeability() {
       if (!this._change) {
@@ -1527,59 +1548,59 @@
       return this.$.restAPI.getMergeable(this._changeNum).then(m => {
         this._mergeable = m.mergeable;
       });
-    },
+    }
 
     _computeCanStartReview(change) {
       return !!(change.actions && change.actions.ready &&
           change.actions.ready.enabled);
-    },
+    }
 
-    _computeReplyDisabled() { return false; },
+    _computeReplyDisabled() { return false; }
 
     _computeChangePermalinkAriaLabel(changeNum) {
       return 'Change ' + changeNum;
-    },
+    }
 
     _computeCommitClass(collapsed, commitMessage) {
       if (this._computeCommitToggleHidden(commitMessage)) { return ''; }
       return collapsed ? 'collapsed' : '';
-    },
+    }
 
     _computeRelatedChangesClass(collapsed) {
       return collapsed ? 'collapsed' : '';
-    },
+    }
 
     _computeCollapseText(collapsed) {
       // Symbols are up and down triangles.
       return collapsed ? '\u25bc Show more' : '\u25b2 Show less';
-    },
+    }
 
     _toggleCommitCollapsed() {
       this._commitCollapsed = !this._commitCollapsed;
       if (this._commitCollapsed) {
         window.scrollTo(0, 0);
       }
-    },
+    }
 
     _toggleRelatedChangesCollapsed() {
       this._relatedChangesCollapsed = !this._relatedChangesCollapsed;
       if (this._relatedChangesCollapsed) {
         window.scrollTo(0, 0);
       }
-    },
+    }
 
     _computeCommitToggleHidden(commitMessage) {
       if (!commitMessage) { return true; }
       return commitMessage.split('\n').length < MIN_LINES_FOR_COMMIT_COLLAPSE;
-    },
+    }
 
     _getOffsetHeight(element) {
       return element.offsetHeight;
-    },
+    }
 
     _getScrollHeight(element) {
       return element.scrollHeight;
-    },
+    }
 
     /**
      * Get the line height of an element to the nearest integer.
@@ -1587,7 +1608,7 @@
     _getLineHeight(element) {
       const lineHeightStr = getComputedStyle(element).lineHeight;
       return Math.round(lineHeightStr.slice(0, lineHeightStr.length - 2));
-    },
+    }
 
     /**
      * New max height for the related changes section, shorter than the existing
@@ -1646,7 +1667,7 @@
       }
 
       this.updateStyles(stylesToUpdate);
-    },
+    }
 
     _computeShowRelatedToggle() {
       // Make sure the max height has been applied, since there is now content
@@ -1666,7 +1687,7 @@
         return this._showRelatedToggle = true;
       }
       this._showRelatedToggle = false;
-    },
+    }
 
     _updateToggleContainerClass(showRelatedToggle) {
       if (showRelatedToggle) {
@@ -1674,7 +1695,7 @@
       } else {
         this.$.relatedChangesToggle.classList.remove('showToggle');
       }
-    },
+    }
 
     _startUpdateCheckTimer() {
       if (!this._serverConfig ||
@@ -1717,14 +1738,14 @@
           });
         });
       }, this._serverConfig.change.update_delay * 1000);
-    },
+    }
 
     _cancelUpdateCheckTimer() {
       if (this._updateCheckTimerHandle) {
         this.cancelAsync(this._updateCheckTimerHandle);
       }
       this._updateCheckTimerHandle = null;
-    },
+    }
 
     _handleVisibilityChange() {
       if (document.hidden && this._updateCheckTimerHandle) {
@@ -1732,17 +1753,17 @@
       } else if (!this._updateCheckTimerHandle) {
         this._startUpdateCheckTimer();
       }
-    },
+    }
 
     _handleTopicChanged() {
       this.$.relatedChanges.reload();
-    },
+    }
 
     _computeHeaderClass(editMode) {
       const classes = ['header'];
       if (editMode) { classes.push('editMode'); }
       return classes.join(' ');
-    },
+    }
 
     _computeEditMode(patchRangeRecord, paramsRecord) {
       if ([patchRangeRecord, paramsRecord].some(arg => arg === undefined)) {
@@ -1753,7 +1774,7 @@
 
       const patchRange = patchRangeRecord.base || {};
       return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
-    },
+    }
 
     _handleFileActionTap(e) {
       e.preventDefault();
@@ -1775,11 +1796,11 @@
           controls.openRestoreDialog(path);
           break;
       }
-    },
+    }
 
     _computeCommitMessageKey(number, revision) {
       return `c${number}_rev${revision}`;
-    },
+    }
 
     _patchNumChanged(patchNumStr) {
       if (!this._selectedRevision) {
@@ -1791,7 +1812,7 @@
       }
       this._selectedRevision = Object.values(this._change.revisions).find(
           revision => revision._number === patchNum);
-    },
+    }
 
     /**
      * If an edit exists already, load it. Otherwise, toggle edit mode via the
@@ -1814,31 +1835,33 @@
         patchNum = this._patchRange.patchNum;
       }
       Gerrit.Nav.navigateToChange(this._change, patchNum, null, true);
-    },
+    }
 
     _handleStopEditTap() {
       Gerrit.Nav.navigateToChange(this._change, this._patchRange.patchNum);
-    },
+    }
 
     _resetReplyOverlayFocusStops() {
       this.$.replyOverlay.setFocusStops(this.$.replyDialog.getFocusStops());
-    },
+    }
 
     _handleToggleStar(e) {
       this.$.restAPI.saveChangeStarred(e.detail.change._number,
           e.detail.starred);
-    },
+    }
 
     _getRevisionInfo(change) {
       return new Gerrit.RevisionInfo(change);
-    },
+    }
 
     _computeCurrentRevision(currentRevision, revisions) {
       return currentRevision && revisions && revisions[currentRevision];
-    },
+    }
 
     _computeDiffPrefsDisabled(disableDiffPrefs, loggedIn) {
       return disableDiffPrefs || !loggedIn;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeView.is, GrChangeView);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index a697b1a..d9b8464 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
index 42cb976..60d459e 100644
--- a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
+++ b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list.js
@@ -16,32 +16,40 @@
  */
 (function() {
   'use strict';
-  Polymer({
-    is: 'gr-comment-list',
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.PathListBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.PathListMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrCommentList extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.PathListBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-comment-list'; }
 
-    properties: {
-      changeNum: Number,
-      comments: Object,
-      patchNum: Number,
-      projectName: String,
-      /** @type {?} */
-      projectConfig: Object,
-    },
+    static get properties() {
+      return {
+        changeNum: Number,
+        comments: Object,
+        patchNum: Number,
+        projectName: String,
+        /** @type {?} */
+        projectConfig: Object,
+      };
+    }
 
     _computeFilesFromComments(comments) {
       const arr = Object.keys(comments || {});
       return arr.sort(this.specialFilePathCompare);
-    },
+    }
 
     _isOnParent(comment) {
       return comment.side === 'PARENT';
-    },
+    }
 
     _computeDiffLineURL(file, changeNum, patchNum, comment) {
       const basePatchNum = comment.hasOwnProperty('parent') ?
@@ -49,13 +57,13 @@
       return Gerrit.Nav.getUrlForDiffById(this.changeNum, this.projectName,
           file, patchNum, basePatchNum, comment.line,
           this._isOnParent(comment));
-    },
+    }
 
     _computeCommentsForFile(comments, file) {
       // Changes are not picked up by the dom-repeat due to the array instance
       // identity not changing even when it has elements added/removed from it.
       return (comments[file] || []).slice();
-    },
+    }
 
     _computePatchDisplayName(comment) {
       if (this._isOnParent(comment)) {
@@ -65,6 +73,8 @@
         return `PS${comment.patch_set}, `;
       }
       return '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCommentList.is, GrCommentList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html
index c18ae8d..97be9b7 100644
--- a/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-comment-list/gr-comment-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-comment-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
index e2fcdff..2a3fe89 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info.js
@@ -17,23 +17,27 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-commit-info',
+  class GrCommitInfo extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-commit-info'; }
 
-    properties: {
-      change: Object,
-      /** @type {?} */
-      commitInfo: Object,
-      serverConfig: Object,
-      _showWebLink: {
-        type: Boolean,
-        computed: '_computeShowWebLink(change, commitInfo, serverConfig)',
-      },
-      _webLink: {
-        type: String,
-        computed: '_computeWebLink(change, commitInfo, serverConfig)',
-      },
-    },
+    static get properties() {
+      return {
+        change: Object,
+        /** @type {?} */
+        commitInfo: Object,
+        serverConfig: Object,
+        _showWebLink: {
+          type: Boolean,
+          computed: '_computeShowWebLink(change, commitInfo, serverConfig)',
+        },
+        _webLink: {
+          type: String,
+          computed: '_computeWebLink(change, commitInfo, serverConfig)',
+        },
+      };
+    }
 
     _getWeblink(change, commitInfo, config) {
       return Gerrit.Nav.getPatchSetWeblink(
@@ -43,7 +47,7 @@
             weblinks: commitInfo.web_links,
             config,
           });
-    },
+    }
 
     _computeShowWebLink(change, commitInfo, serverConfig) {
       // Polymer 2: check for undefined
@@ -53,7 +57,7 @@
 
       const weblink = this._getWeblink(change, commitInfo, serverConfig);
       return !!weblink && !!weblink.url;
-    },
+    }
 
     _computeWebLink(change, commitInfo, serverConfig) {
       // Polymer 2: check for undefined
@@ -63,12 +67,14 @@
 
       const {url} = this._getWeblink(change, commitInfo, serverConfig) || {};
       return url;
-    },
+    }
 
     _computeShortHash(commitInfo) {
       const {name} =
             this._getWeblink(this.change, commitInfo, this.serverConfig) || {};
       return name;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCommitInfo.is, GrCommitInfo);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html
index d3b33d1..2c5b431 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-commit-info</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.js
index 524876e..6ef5b69 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.js
@@ -17,9 +17,17 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-confirm-abandon-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrConfirmAbandonDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-abandon-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -32,41 +40,42 @@
      * @event cancel
      */
 
-    properties: {
-      message: String,
-    },
+    static get properties() {
+      return {
+        message: String,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    keyBindings: {
-      'ctrl+enter meta+enter': '_handleEnterKey',
-    },
+    get keyBindings() {
+      return {
+        'ctrl+enter meta+enter': '_handleEnterKey',
+      };
+    }
 
     resetFocus() {
       this.$.messageInput.textarea.focus();
-    },
+    }
 
     _handleEnterKey(e) {
       this._confirm();
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this._confirm();
-    },
+    }
 
     _confirm() {
       this.fire('confirm', {reason: this.message}, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmAbandonDialog.is, GrConfirmAbandonDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html
index cc4b80e..e9964c5 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-abandon-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.js
index a0da331..669c6b1 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.js
@@ -17,12 +17,15 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-confirm-cherrypick-conflict-dialog',
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmCherrypickConflictDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-cherrypick-conflict-dialog'; }
 
     /**
      * Fired when the confirm button is pressed.
@@ -40,12 +43,15 @@
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmCherrypickConflictDialog.is,
+      GrConfirmCherrypickConflictDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html
index f411de4..557972a 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-cherrypick-conflict-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
index 5278540..bdc5c10 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.js
@@ -19,9 +19,15 @@
 
   const SUGGESTIONS_LIMIT = 15;
 
-  Polymer({
-    is: 'gr-confirm-cherrypick-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmCherrypickDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-cherrypick-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -34,29 +40,29 @@
      * @event cancel
      */
 
-    properties: {
-      branch: String,
-      baseCommit: String,
-      changeStatus: String,
-      commitMessage: String,
-      commitNum: String,
-      message: String,
-      project: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getProjectBranchesSuggestions.bind(this);
+    static get properties() {
+      return {
+        branch: String,
+        baseCommit: String,
+        changeStatus: String,
+        commitMessage: String,
+        commitNum: String,
+        message: String,
+        project: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getProjectBranchesSuggestions.bind(this);
+          },
         },
-      },
-    },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_computeMessage(changeStatus, commitNum, commitMessage)',
-    ],
+    static get observers() {
+      return [
+        '_computeMessage(changeStatus, commitNum, commitMessage)',
+      ];
+    }
 
     _computeMessage(changeStatus, commitNum, commitMessage) {
       // Polymer 2: check for undefined
@@ -74,23 +80,23 @@
         newMessage += '(cherry picked from commit ' + commitNum + ')';
       }
       this.message = newMessage;
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
+    }
 
     resetFocus() {
       this.$.branchInput.focus();
-    },
+    }
 
     _getProjectBranchesSuggestions(input) {
       if (input.startsWith('refs/heads/')) {
@@ -113,6 +119,9 @@
         }
         return branches;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmCherrypickDialog.is,
+      GrConfirmCherrypickDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html
index 22a2aba..42310fb 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-cherrypick-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.js
index c6b0adf..fb78bfb 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.js
@@ -19,9 +19,15 @@
 
   const SUGGESTIONS_LIMIT = 15;
 
-  Polymer({
-    is: 'gr-confirm-move-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmMoveDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-move-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -34,33 +40,31 @@
      * @event cancel
      */
 
-    properties: {
-      branch: String,
-      message: String,
-      project: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getProjectBranchesSuggestions.bind(this);
+    static get properties() {
+      return {
+        branch: String,
+        message: String,
+        project: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getProjectBranchesSuggestions.bind(this);
+          },
         },
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+      };
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
+    }
 
     _getProjectBranchesSuggestions(input) {
       if (input.startsWith('refs/heads/')) {
@@ -83,6 +87,8 @@
         }
         return branches;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmMoveDialog.is, GrConfirmMoveDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html
index 8d6e029..036950b 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-move-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
index 54ce271..7169437 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.js
@@ -17,9 +17,10 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-confirm-rebase-dialog',
-
+  class GrConfirmRebaseDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-confirm-rebase-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -32,24 +33,28 @@
      * @event cancel
      */
 
-    properties: {
-      branch: String,
-      changeNumber: Number,
-      hasParent: Boolean,
-      rebaseOnCurrent: Boolean,
-      _text: String,
-      _query: {
-        type: Function,
-        value() {
-          return this._getChangeSuggestions.bind(this);
+    static get properties() {
+      return {
+        branch: String,
+        changeNumber: Number,
+        hasParent: Boolean,
+        rebaseOnCurrent: Boolean,
+        _text: String,
+        _query: {
+          type: Function,
+          value() {
+            return this._getChangeSuggestions.bind(this);
+          },
         },
-      },
-      _recentChanges: Array,
-    },
+        _recentChanges: Array,
+      };
+    }
 
-    observers: [
-      '_updateSelectedOption(rebaseOnCurrent, hasParent)',
-    ],
+    static get observers() {
+      return [
+        '_updateSelectedOption(rebaseOnCurrent, hasParent)',
+      ];
+    }
 
     // This is called by gr-change-actions every time the rebase dialog is
     // re-opened. Unlike other autocompletes that make a request with each
@@ -71,36 +76,36 @@
             this._recentChanges = changes;
             return this._recentChanges;
           });
-    },
+    }
 
     _getRecentChanges() {
       if (this._recentChanges) {
         return Promise.resolve(this._recentChanges);
       }
       return this.fetchRecentChanges();
-    },
+    }
 
     _getChangeSuggestions(input) {
       return this._getRecentChanges().then(changes =>
         this._filterChanges(input, changes));
-    },
+    }
 
     _filterChanges(input, changes) {
       return changes.filter(change => change.name.includes(input) &&
           change.value !== this.changeNumber);
-    },
+    }
 
     _displayParentOption(rebaseOnCurrent, hasParent) {
       return hasParent && rebaseOnCurrent;
-    },
+    }
 
     _displayParentUpToDateMsg(rebaseOnCurrent, hasParent) {
       return hasParent && !rebaseOnCurrent;
-    },
+    }
 
     _displayTipOption(rebaseOnCurrent, hasParent) {
       return !(!rebaseOnCurrent && !hasParent);
-    },
+    }
 
     /**
      * There is a subtle but important difference between setting the base to an
@@ -115,7 +120,7 @@
       // Change numbers will have their description appended by the
       // autocomplete.
       return this._text.split(':')[0];
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
@@ -123,22 +128,22 @@
       this.dispatchEvent(new CustomEvent('confirm',
           {detail: {base: this._getSelectedBase()}}));
       this._text = '';
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.dispatchEvent(new CustomEvent('cancel'));
       this._text = '';
-    },
+    }
 
     _handleRebaseOnOther() {
       this.$.parentInput.focus();
-    },
+    }
 
     _handleEnterChangeNumberClick() {
       this.$.rebaseOnOtherInput.checked = true;
-    },
+    }
 
     /**
      * Sets the default radio button based on the state of the app and
@@ -157,6 +162,8 @@
       } else {
         this.$.rebaseOnOtherInput.checked = true;
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmRebaseDialog.is, GrConfirmRebaseDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
index cd5b130..b116171 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-rebase-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.html b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.html
index e744668..2e1e6ae 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.html
@@ -20,6 +20,7 @@
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../shared/gr-dialog/gr-dialog.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
 
 <dom-module id="gr-confirm-revert-dialog">
   <template>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.js
index 662b64c..e95f2c9 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.js
@@ -20,9 +20,15 @@
   const ERR_COMMIT_NOT_FOUND =
       'Unable to find the commit hash of this change.';
 
-  Polymer({
-    is: 'gr-confirm-revert-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmRevertDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-revert-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -35,13 +41,11 @@
      * @event cancel
      */
 
-    properties: {
-      message: String,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        message: String,
+      };
+    }
 
     populateRevertMessage(message, commitHash) {
       // Figure out what the revert title should be.
@@ -55,18 +59,20 @@
 
       this.message = `${revertTitle}\n\n${revertCommitText}\n\n` +
           `Reason for revert: <INSERT REASONING HERE>\n`;
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmRevertDialog.is, GrConfirmRevertDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html
index 6e41555..dbdfba2 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-revert-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
index 6cbbb37..04b16ee 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog.js
@@ -20,9 +20,15 @@
   const ERR_COMMIT_NOT_FOUND =
       'Unable to find the commit hash of this change.';
 
-  Polymer({
-    is: 'gr-confirm-revert-submission-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmRevertSubmissionDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-revert-submission-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -35,13 +41,11 @@
      * @event cancel
      */
 
-    properties: {
-      message: String,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        message: String,
+      };
+    }
 
     populateRevertSubmissionMessage(message, commitHash) {
       // Follow the same convention of the revert
@@ -52,18 +56,21 @@
       }
       this.message = `${revertTitle}\n\n` +
           `Reason for revert: <INSERT REASONING HERE>\n`;
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmRevertSubmissionDialog.is,
+      GrConfirmRevertSubmissionDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html
index c0f2dc3..cc4bd54 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-submission-dialog/gr-confirm-revert-submission-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-revert-submission-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.html b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.html
index 40d4d2d..1a1276d 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.html
@@ -20,6 +20,8 @@
 <link rel="import" href="../../core/gr-navigation/gr-navigation.html">
 <link rel="import" href="../../shared/gr-dialog/gr-dialog.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+<link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
+<link rel="import" href="../../plugins/gr-endpoint-param/gr-endpoint-param.html">
 <link rel="import" href="../../../styles/shared-styles.html">
 
 <dom-module id="gr-confirm-submit-dialog">
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.js b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.js
index e86e21c..05841e9 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.js
@@ -17,9 +17,10 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-confirm-submit-dialog',
-
+  class GrConfirmSubmitDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-confirm-submit-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -32,37 +33,41 @@
      * @event cancel
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * @type {{
        *    is_private: boolean,
        *    subject: string,
        *  }}
        */
-      change: Object,
+        change: Object,
 
-      /**
+        /**
        * @type {{
        *    label: string,
        *  }}
        */
-      action: Object,
-    },
+        action: Object,
+      };
+    }
 
     resetFocus(e) {
       this.$.dialog.resetFocus();
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.dispatchEvent(new CustomEvent('confirm', {bubbles: false}));
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.dispatchEvent(new CustomEvent('cancel', {bubbles: false}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmSubmitDialog.is, GrConfirmSubmitDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html
index 40fa29a..515147f 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-confirm-submit-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
index b2e5e63..ab849de 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
@@ -17,40 +17,47 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-download-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrDownloadDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-download-dialog'; }
     /**
      * Fired when the user presses the close button.
      *
      * @event close
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {{ revisions: Array }} */
-      change: Object,
-      patchNum: String,
-      /** @type {?} */
-      config: Object,
+        change: Object,
+        patchNum: String,
+        /** @type {?} */
+        config: Object,
 
-      _schemes: {
-        type: Array,
-        value() { return []; },
-        computed: '_computeSchemes(change, patchNum)',
-        observer: '_schemesChanged',
-      },
-      _selectedScheme: String,
-    },
+        _schemes: {
+          type: Array,
+          value() { return []; },
+          computed: '_computeSchemes(change, patchNum)',
+          observer: '_schemesChanged',
+        },
+        _selectedScheme: String,
+      };
+    }
 
-    hostAttributes: {
-      role: 'dialog',
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'dialog');
+    }
 
     focus() {
       if (this._schemes.length) {
@@ -58,7 +65,7 @@
       } else {
         this.$.download.focus();
       }
-    },
+    }
 
     getFocusStops() {
       const links = this.$$('#archives').querySelectorAll('a');
@@ -66,7 +73,7 @@
         start: this.$.closeButton,
         end: links[links.length - 1],
       };
-    },
+    }
 
     _computeDownloadCommands(change, patchNum, _selectedScheme) {
       let commandObj;
@@ -87,7 +94,7 @@
         });
       }
       return commands;
-    },
+    }
 
     /**
      * @param {!Object} change
@@ -97,7 +104,7 @@
      */
     _computeZipDownloadLink(change, patchNum) {
       return this._computeDownloadLink(change, patchNum, true);
-    },
+    }
 
     /**
      * @param {!Object} change
@@ -107,7 +114,7 @@
      */
     _computeZipDownloadFilename(change, patchNum) {
       return this._computeDownloadFilename(change, patchNum, true);
-    },
+    }
 
     /**
      * @param {!Object} change
@@ -123,7 +130,7 @@
       }
       return this.changeBaseURL(change.project, change._number, patchNum) +
           '/patch?' + (opt_zip ? 'zip' : 'download');
-    },
+    }
 
     /**
      * @param {!Object} change
@@ -146,7 +153,7 @@
         }
       }
       return shortRev + '.diff.' + (opt_zip ? 'zip' : 'base64');
-    },
+    }
 
     _computeHidePatchFile(change, patchNum) {
       // Polymer 2: check for undefined
@@ -161,7 +168,7 @@
         }
       }
       return false;
-    },
+    }
 
     _computeArchiveDownloadLink(change, patchNum, format) {
       // Polymer 2: check for undefined
@@ -170,7 +177,7 @@
       }
       return this.changeBaseURL(change.project, change._number, patchNum) +
           '/archive?format=' + format;
-    },
+    }
 
     _computeSchemes(change, patchNum) {
       // Polymer 2: check for undefined
@@ -188,28 +195,30 @@
         }
       }
       return [];
-    },
+    }
 
     _computePatchSetQuantity(revisions) {
       if (!revisions) { return 0; }
       return Object.keys(revisions).length;
-    },
+    }
 
     _handleCloseTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('close', null, {bubbles: false});
-    },
+    }
 
     _schemesChanged(schemes) {
       if (schemes.length === 0) { return; }
       if (!schemes.includes(this._selectedScheme)) {
         this._selectedScheme = schemes.sort()[0];
       }
-    },
+    }
 
     _computeShowDownloadCommands(schemes) {
       return schemes.length ? '' : 'hidden';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDownloadDialog.is, GrDownloadDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
index 82574808..0f1260f 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-download-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
index e31ce26..9146125 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.html
@@ -30,6 +30,7 @@
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-icons/gr-icons.html">
 <link rel="import" href="../gr-file-list-constants.html">
+<link rel="import" href="../gr-commit-info/gr-commit-info.html">
 
 <dom-module id="gr-file-list-header">
   <template>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
index b8095bf..dded147 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.js
@@ -21,9 +21,17 @@
   const PATCH_DESC_MAX_LENGTH = 500;
   const MERGED_STATUS = 'MERGED';
 
-  Polymer({
-    is: 'gr-file-list-header',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrFileListHeader extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-file-list-header'; }
     /**
      * @event expand-diffs
      */
@@ -48,72 +56,71 @@
      * @event open-upload-help-dialog
      */
 
-    properties: {
-      account: Object,
-      allPatchSets: Array,
-      /** @type {?} */
-      change: Object,
-      changeNum: String,
-      changeUrl: String,
-      changeComments: Object,
-      commitInfo: Object,
-      editMode: Boolean,
-      loggedIn: Boolean,
-      serverConfig: Object,
-      shownFileCount: Number,
-      diffPrefs: Object,
-      diffPrefsDisabled: Boolean,
-      diffViewMode: {
-        type: String,
-        notify: true,
-      },
-      patchNum: String,
-      basePatchNum: String,
-      filesExpanded: String,
-      // Caps the number of files that can be shown and have the 'show diffs' /
-      // 'hide diffs' buttons still be functional.
-      _maxFilesForBulkActions: {
-        type: Number,
-        readOnly: true,
-        value: 225,
-      },
-      _patchsetDescription: {
-        type: String,
-        value: '',
-      },
-      showTitle: {
-        type: Boolean,
-        value: true,
-      },
-      _descriptionReadOnly: {
-        type: Boolean,
-        computed: '_computeDescriptionReadOnly(loggedIn, change, account)',
-      },
-      revisionInfo: Object,
-    },
+    static get properties() {
+      return {
+        account: Object,
+        allPatchSets: Array,
+        /** @type {?} */
+        change: Object,
+        changeNum: String,
+        changeUrl: String,
+        changeComments: Object,
+        commitInfo: Object,
+        editMode: Boolean,
+        loggedIn: Boolean,
+        serverConfig: Object,
+        shownFileCount: Number,
+        diffPrefs: Object,
+        diffPrefsDisabled: Boolean,
+        diffViewMode: {
+          type: String,
+          notify: true,
+        },
+        patchNum: String,
+        basePatchNum: String,
+        filesExpanded: String,
+        // Caps the number of files that can be shown and have the 'show diffs' /
+        // 'hide diffs' buttons still be functional.
+        _maxFilesForBulkActions: {
+          type: Number,
+          readOnly: true,
+          value: 225,
+        },
+        _patchsetDescription: {
+          type: String,
+          value: '',
+        },
+        showTitle: {
+          type: Boolean,
+          value: true,
+        },
+        _descriptionReadOnly: {
+          type: Boolean,
+          computed: '_computeDescriptionReadOnly(loggedIn, change, account)',
+        },
+        revisionInfo: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-    ],
-
-    observers: [
-      '_computePatchSetDescription(change, patchNum)',
-    ],
+    static get observers() {
+      return [
+        '_computePatchSetDescription(change, patchNum)',
+      ];
+    }
 
     setDiffViewMode(mode) {
       this.$.modeSelect.setMode(mode);
-    },
+    }
 
     _expandAllDiffs() {
       this._expanded = true;
       this.fire('expand-diffs');
-    },
+    }
 
     _collapseAllDiffs() {
       this._expanded = false;
       this.fire('collapse-diffs');
-    },
+    }
 
     _computeExpandedClass(filesExpanded) {
       const classes = [];
@@ -125,11 +132,11 @@
         classes.push('openFile');
       }
       return classes.join(' ');
-    },
+    }
 
     _computeDescriptionPlaceholder(readOnly) {
       return (readOnly ? 'No' : 'Add') + ' patchset description';
-    },
+    }
 
     _computeDescriptionReadOnly(loggedIn, change, account) {
       // Polymer 2: check for undefined
@@ -138,7 +145,7 @@
       }
 
       return !(loggedIn && (account._account_id === change.owner._account_id));
-    },
+    }
 
     _computePatchSetDescription(change, patchNum) {
       // Polymer 2: check for undefined
@@ -149,11 +156,11 @@
       const rev = this.getRevisionByPatchNum(change.revisions, patchNum);
       this._patchsetDescription = (rev && rev.description) ?
         rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
-    },
+    }
 
     _handleDescriptionRemoved(e) {
       return this._updateDescription('', e);
-    },
+    }
 
     /**
      * @param {!Object} revisions The revisions object keyed by revision hashes
@@ -167,12 +174,12 @@
           return rev;
         }
       }
-    },
+    }
 
     _handleDescriptionChanged(e) {
       const desc = e.detail.trim();
       this._updateDescription(desc, e);
-    },
+    }
 
     /**
      * Update the patchset description with the rest API.
@@ -197,43 +204,43 @@
             if (target) { target.disabled = false; }
             return;
           });
-    },
+    }
 
     _computePrefsButtonHidden(prefs, diffPrefsDisabled) {
       return diffPrefsDisabled || !prefs;
-    },
+    }
 
     _fileListActionsVisible(shownFileCount, maxFilesForBulkActions) {
       return shownFileCount <= maxFilesForBulkActions;
-    },
+    }
 
     _handlePatchChange(e) {
       const {basePatchNum, patchNum} = e.detail;
       if (this.patchNumEquals(basePatchNum, this.basePatchNum) &&
           this.patchNumEquals(patchNum, this.patchNum)) { return; }
       Gerrit.Nav.navigateToChange(this.change, patchNum, basePatchNum);
-    },
+    }
 
     _handlePrefsTap(e) {
       e.preventDefault();
       this.fire('open-diff-prefs');
-    },
+    }
 
     _handleIncludedInTap(e) {
       e.preventDefault();
       this.fire('open-included-in-dialog');
-    },
+    }
 
     _handleDownloadTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.dispatchEvent(
           new CustomEvent('open-download-dialog', {bubbles: false}));
-    },
+    }
 
     _computeEditModeClass(editMode) {
       return editMode ? 'editMode' : '';
-    },
+    }
 
     _computePatchInfoClass(patchNum, allPatchSets) {
       const latestNum = this.computeLatestPatchNum(allPatchSets);
@@ -241,18 +248,18 @@
         return '';
       }
       return 'patchInfoOldPatchSet';
-    },
+    }
 
     _hideIncludedIn(change) {
       return change && change.status === MERGED_STATUS ? '' : 'hide';
-    },
+    }
 
     _handleUploadTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.dispatchEvent(
           new CustomEvent('open-upload-help-dialog', {bubbles: false}));
-    },
+    }
 
     _computeUploadHelpContainerClass(change, account) {
       const changeIsMerged = change && change.status === MERGED_STATUS;
@@ -262,6 +269,8 @@
       const userIsOwner = ownerId && userId && ownerId === userId;
       const hideContainer = !userIsOwner || changeIsMerged;
       return 'uploadContainer desktop' + (hideContainer ? ' hide' : '');
-    },
-  });
+    }
+  }
+
+  customElements.define(GrFileListHeader.is, GrFileListHeader);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
index ac626ab..ea7ea8f 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-file-list-header</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index 0668e14..318633d 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -433,7 +433,6 @@
                 no-auto-render
                 show-load-failure
                 display-line="[[_displayLine]]"
-                inline-index=[[index]]
                 hidden="[[!_isFileExpanded(file.__path, _expandedFilePaths.*)]]"
                 change-num="[[changeNum]]"
                 patch-range="[[patchRange]]"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index 6c44694..fb57164 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -41,162 +41,175 @@
     U: 'Unchanged',
   };
 
-  Polymer({
-    is: 'gr-file-list',
-
+  /**
+    * @appliesMixin Gerrit.AsyncForeachMixin
+    * @appliesMixin Gerrit.DomUtilMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.PathListMixin
+    */
+  class GrFileList extends Polymer.mixinBehaviors( [
+    Gerrit.AsyncForeachBehavior,
+    Gerrit.DomUtilBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.PathListBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-file-list'; }
     /**
      * Fired when a draft refresh should get triggered
      *
      * @event reload-drafts
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      patchRange: Object,
-      patchNum: String,
-      changeNum: String,
-      /** @type {?} */
-      changeComments: Object,
-      drafts: Object,
-      revisions: Array,
-      projectConfig: Object,
-      selectedIndex: {
-        type: Number,
-        notify: true,
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      /** @type {?} */
-      change: Object,
-      diffViewMode: {
-        type: String,
-        notify: true,
-        observer: '_updateDiffPreferences',
-      },
-      editMode: {
-        type: Boolean,
-        observer: '_editModeChanged',
-      },
-      filesExpanded: {
-        type: String,
-        value: GrFileListConstants.FilesExpandedState.NONE,
-        notify: true,
-      },
-      _filesByPath: Object,
-      _files: {
-        type: Array,
-        observer: '_filesChanged',
-        value() { return []; },
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-      _reviewed: {
-        type: Array,
-        value() { return []; },
-      },
-      diffPrefs: {
-        type: Object,
-        notify: true,
-        observer: '_updateDiffPreferences',
-      },
-      /** @type {?} */
-      _userPrefs: Object,
-      _showInlineDiffs: Boolean,
-      numFilesShown: {
-        type: Number,
-        notify: true,
-      },
-      /** @type {?} */
-      _patchChange: {
-        type: Object,
-        computed: '_calculatePatchChange(_files)',
-      },
-      fileListIncrement: Number,
-      _hideChangeTotals: {
-        type: Boolean,
-        computed: '_shouldHideChangeTotals(_patchChange)',
-      },
-      _hideBinaryChangeTotals: {
-        type: Boolean,
-        computed: '_shouldHideBinaryChangeTotals(_patchChange)',
-      },
+        patchRange: Object,
+        patchNum: String,
+        changeNum: String,
+        /** @type {?} */
+        changeComments: Object,
+        drafts: Object,
+        revisions: Array,
+        projectConfig: Object,
+        selectedIndex: {
+          type: Number,
+          notify: true,
+        },
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        /** @type {?} */
+        change: Object,
+        diffViewMode: {
+          type: String,
+          notify: true,
+          observer: '_updateDiffPreferences',
+        },
+        editMode: {
+          type: Boolean,
+          observer: '_editModeChanged',
+        },
+        filesExpanded: {
+          type: String,
+          value: GrFileListConstants.FilesExpandedState.NONE,
+          notify: true,
+        },
+        _filesByPath: Object,
+        _files: {
+          type: Array,
+          observer: '_filesChanged',
+          value() { return []; },
+        },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+        _reviewed: {
+          type: Array,
+          value() { return []; },
+        },
+        diffPrefs: {
+          type: Object,
+          notify: true,
+          observer: '_updateDiffPreferences',
+        },
+        /** @type {?} */
+        _userPrefs: Object,
+        _showInlineDiffs: Boolean,
+        numFilesShown: {
+          type: Number,
+          notify: true,
+        },
+        /** @type {?} */
+        _patchChange: {
+          type: Object,
+          computed: '_calculatePatchChange(_files)',
+        },
+        fileListIncrement: Number,
+        _hideChangeTotals: {
+          type: Boolean,
+          computed: '_shouldHideChangeTotals(_patchChange)',
+        },
+        _hideBinaryChangeTotals: {
+          type: Boolean,
+          computed: '_shouldHideBinaryChangeTotals(_patchChange)',
+        },
 
-      _shownFiles: {
-        type: Array,
-        computed: '_computeFilesShown(numFilesShown, _files)',
-      },
+        _shownFiles: {
+          type: Array,
+          computed: '_computeFilesShown(numFilesShown, _files)',
+        },
 
-      /**
+        /**
        * The amount of files added to the shown files list the last time it was
        * updated. This is used for reporting the average render time.
        */
-      _reportinShownFilesIncrement: Number,
+        _reportinShownFilesIncrement: Number,
 
-      _expandedFilePaths: {
-        type: Array,
-        value() { return []; },
-      },
-      _displayLine: Boolean,
-      _loading: {
-        type: Boolean,
-        observer: '_loadingChanged',
-      },
-      /** @type {Gerrit.LayoutStats|undefined} */
-      _sizeBarLayout: {
-        type: Object,
-        computed: '_computeSizeBarLayout(_shownFiles.*)',
-      },
+        _expandedFilePaths: {
+          type: Array,
+          value() { return []; },
+        },
+        _displayLine: Boolean,
+        _loading: {
+          type: Boolean,
+          observer: '_loadingChanged',
+        },
+        /** @type {Gerrit.LayoutStats|undefined} */
+        _sizeBarLayout: {
+          type: Object,
+          computed: '_computeSizeBarLayout(_shownFiles.*)',
+        },
 
-      _showSizeBars: {
-        type: Boolean,
-        value: true,
-        computed: '_computeShowSizeBars(_userPrefs)',
-      },
+        _showSizeBars: {
+          type: Boolean,
+          value: true,
+          computed: '_computeShowSizeBars(_userPrefs)',
+        },
 
-      /** @type {Function} */
-      _cancelForEachDiff: Function,
+        /** @type {Function} */
+        _cancelForEachDiff: Function,
 
-      _showDynamicColumns: {
-        type: Boolean,
-        computed: '_computeShowDynamicColumns(_dynamicHeaderEndpoints, ' +
+        _showDynamicColumns: {
+          type: Boolean,
+          computed: '_computeShowDynamicColumns(_dynamicHeaderEndpoints, ' +
                   '_dynamicContentEndpoints, _dynamicSummaryEndpoints)',
-      },
-      /** @type {Array<string>} */
-      _dynamicHeaderEndpoints: {
-        type: Array,
-      },
-      /** @type {Array<string>} */
-      _dynamicContentEndpoints: {
-        type: Array,
-      },
-      /** @type {Array<string>} */
-      _dynamicSummaryEndpoints: {
-        type: Array,
-      },
-    },
+        },
+        /** @type {Array<string>} */
+        _dynamicHeaderEndpoints: {
+          type: Array,
+        },
+        /** @type {Array<string>} */
+        _dynamicContentEndpoints: {
+          type: Array,
+        },
+        /** @type {Array<string>} */
+        _dynamicSummaryEndpoints: {
+          type: Array,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.AsyncForeachBehavior,
-      Gerrit.DomUtilBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.PathListBehavior,
-    ],
-
-    observers: [
-      '_expandedPathsChanged(_expandedFilePaths.splices)',
-      '_computeFiles(_filesByPath, changeComments, patchRange, _reviewed, ' +
+    static get observers() {
+      return [
+        '_expandedPathsChanged(_expandedFilePaths.splices)',
+        '_computeFiles(_filesByPath, changeComments, patchRange, _reviewed, ' +
           '_loading)',
-    ],
+      ];
+    }
 
-    keyBindings: {
-      esc: '_handleEscKey',
-    },
+    get keyBindings() {
+      return {
+        esc: '_handleEscKey',
+      };
+    }
 
     keyboardShortcuts() {
       return {
@@ -221,12 +234,16 @@
         [this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
         [this.Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
       };
-    },
-    listeners: {
-      keydown: '_scopedKeydownHandler',
-    },
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('keydown',
+          e => this._scopedKeydownHandler(e));
+    }
 
     attached() {
+      super.attached();
       Gerrit.awaitPluginsLoaded().then(() => {
         this._dynamicHeaderEndpoints = Gerrit._endpoints.getDynamicEndpoints(
             'change-view-file-list-header');
@@ -246,11 +263,12 @@
               'Different number of dynamic file-list headers and summary.');
         }
       });
-    },
+    }
 
     detached() {
+      super.detached();
       this._cancelDiffs();
-    },
+    }
 
     /**
      * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
@@ -264,7 +282,7 @@
         // Enter.
         this._handleOpenFile(e);
       }
-    },
+    }
 
     reload() {
       if (!this.changeNum || !this.patchRange.patchNum) {
@@ -302,23 +320,23 @@
         this._detectChromiteButler();
         this.$.reporting.fileListDisplayed();
       });
-    },
+    }
 
     _detectChromiteButler() {
       const hasButler = !!document.getElementById('butler-suggested-owners');
       if (hasButler) {
         this.$.reporting.reportExtension('butler');
       }
-    },
+    }
 
     get diffs() {
       return Array.from(
           Polymer.dom(this.root).querySelectorAll('gr-diff-host'));
-    },
+    }
 
     openDiffPrefs() {
       this.$.diffPreferencesDialog.open();
-    },
+    }
 
     _calculatePatchChange(files) {
       const magicFilesExcluded = files.filter(files => {
@@ -343,15 +361,15 @@
         };
       }, {inserted: 0, deleted: 0, size_delta_inserted: 0,
         size_delta_deleted: 0, total_size: 0});
-    },
+    }
 
     _getDiffPreferences() {
       return this.$.restAPI.getDiffPreferences();
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     _togglePathExpanded(path) {
       // Is the path in the list of expanded diffs? IF so remove it, otherwise
@@ -362,11 +380,11 @@
       } else {
         this.splice('_expandedFilePaths', pathIndex, 1);
       }
-    },
+    }
 
     _togglePathExpandedByIndex(index) {
       this._togglePathExpanded(this._files[index].__path);
-    },
+    }
 
     _updateDiffPreferences() {
       if (!this.diffs.length) { return; }
@@ -374,14 +392,14 @@
       this.$.reporting.time(EXPAND_ALL_TIMING_LABEL);
       this._renderInOrder(this._expandedFilePaths, this.diffs,
           this._expandedFilePaths.length);
-    },
+    }
 
     _forEachDiff(fn) {
       const diffs = this.diffs;
       for (let i = 0; i < diffs.length; i++) {
         fn(diffs[i]);
       }
-    },
+    }
 
     expandAllDiffs() {
       this._showInlineDiffs = true;
@@ -398,7 +416,7 @@
       }
 
       this.splice(...['_expandedFilePaths', 0, 0].concat(newPaths));
-    },
+    }
 
     collapseAllDiffs() {
       this._showInlineDiffs = false;
@@ -406,7 +424,7 @@
       this.filesExpanded = this._computeExpandedFiles(
           this._expandedFilePaths.length, this._files.length);
       this.$.diffCursor.handleDiffUpdate();
-    },
+    }
 
     /**
      * Computes a string with the number of comments and unresolved comments.
@@ -433,7 +451,7 @@
           (commentString && unresolvedString ? ' ' : '') +
           // Add parentheses around unresolved if it exists.
           (unresolvedString ? `(${unresolvedString})` : '');
-    },
+    }
 
     /**
      * Computes a string with the number of drafts.
@@ -448,7 +466,7 @@
           changeComments.computeDraftCount(patchRange.basePatchNum, path) +
           changeComments.computeDraftCount(patchRange.patchNum, path);
       return GrCountStringFormatter.computePluralString(draftCount, 'draft');
-    },
+    }
 
     /**
      * Computes a shortened string with the number of drafts.
@@ -463,7 +481,7 @@
           changeComments.computeDraftCount(patchRange.basePatchNum, path) +
           changeComments.computeDraftCount(patchRange.patchNum, path);
       return GrCountStringFormatter.computeShortString(draftCount, 'd');
-    },
+    }
 
     /**
      * Computes a shortened string with the number of comments.
@@ -478,7 +496,7 @@
           changeComments.computeCommentCount(patchRange.basePatchNum, path) +
           changeComments.computeCommentCount(patchRange.patchNum, path);
       return GrCountStringFormatter.computeShortString(commentCount, 'c');
-    },
+    }
 
     /**
      * @param {string} path
@@ -495,27 +513,27 @@
       }
 
       this._saveReviewedState(path, reviewed);
-    },
+    }
 
     _saveReviewedState(path, reviewed) {
       return this.$.restAPI.saveFileReviewed(this.changeNum,
           this.patchRange.patchNum, path, reviewed);
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getReviewedFiles() {
       if (this.editMode) { return Promise.resolve([]); }
       return this.$.restAPI.getReviewedFiles(this.changeNum,
           this.patchRange.patchNum);
-    },
+    }
 
     _getFiles() {
       return this.$.restAPI.getChangeOrEditFiles(
           this.changeNum, this.patchRange);
-    },
+    }
 
     /**
      * The closure compiler doesn't realize this.specialFilePathCompare is
@@ -534,7 +552,7 @@
         files.push(info);
       }
       return files;
-    },
+    }
 
     /**
      * Handle all events from the file list dom-repeat so event handleers don't
@@ -564,7 +582,7 @@
 
       e.preventDefault();
       this._togglePathExpanded(path);
-    },
+    }
 
     _handleLeftPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e) || this._noDiffsExpanded()) {
@@ -573,7 +591,7 @@
 
       e.preventDefault();
       this.$.diffCursor.moveLeft();
-    },
+    }
 
     _handleRightPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e) || this._noDiffsExpanded()) {
@@ -582,7 +600,7 @@
 
       e.preventDefault();
       this.$.diffCursor.moveRight();
-    },
+    }
 
     _handleToggleInlineDiff(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -591,14 +609,14 @@
 
       e.preventDefault();
       this._togglePathExpandedByIndex(this.$.fileCursor.index);
-    },
+    }
 
     _handleToggleAllInlineDiffs(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       e.preventDefault();
       this._toggleInlineDiffs();
-    },
+    }
 
     _handleCursorNext(e) {
       if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
@@ -616,7 +634,7 @@
         this.$.fileCursor.next();
         this.selectedIndex = this.$.fileCursor.index;
       }
-    },
+    }
 
     _handleCursorPrev(e) {
       if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
@@ -634,20 +652,14 @@
         this.$.fileCursor.previous();
         this.selectedIndex = this.$.fileCursor.index;
       }
-    },
+    }
 
     _handleNewComment(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
           this.modifierPressed(e)) { return; }
-
-      const isRangeSelected = this.diffs.some(diff => {
-        return diff.isRangeSelected();
-      }, this);
-      if (!isRangeSelected) {
-        e.preventDefault();
-        this._addDraftAtTarget();
-      }
-    },
+      e.preventDefault();
+      this.$.diffCursor.createCommentInPlace();
+    }
 
     _handleOpenLastFile(e) {
       // Check for meta key to avoid overriding native chrome shortcut.
@@ -656,7 +668,7 @@
 
       e.preventDefault();
       this._openSelectedFile(this._files.length - 1);
-    },
+    }
 
     _handleOpenFirstFile(e) {
       // Check for meta key to avoid overriding native chrome shortcut.
@@ -665,7 +677,7 @@
 
       e.preventDefault();
       this._openSelectedFile(0);
-    },
+    }
 
     _handleOpenFile(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -678,7 +690,7 @@
       }
 
       this._openSelectedFile();
-    },
+    }
 
     _handleNextChunk(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -693,7 +705,7 @@
       } else {
         this.$.diffCursor.moveToNextChunk();
       }
-    },
+    }
 
     _handlePrevChunk(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -708,7 +720,7 @@
       } else {
         this.$.diffCursor.moveToPreviousChunk();
       }
-    },
+    }
 
     _handleToggleFileReviewed(e) {
       if (this.shouldSuppressKeyboardShortcut(e) || this.modifierPressed(e)) {
@@ -718,7 +730,7 @@
       e.preventDefault();
       if (!this._files[this.$.fileCursor.index]) { return; }
       this._reviewFile(this._files[this.$.fileCursor.index].__path);
-    },
+    }
 
     _handleToggleLeftPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -727,7 +739,7 @@
       this._forEachDiff(diff => {
         diff.toggleLeftDiff();
       });
-    },
+    }
 
     _toggleInlineDiffs() {
       if (this._showInlineDiffs) {
@@ -735,13 +747,13 @@
       } else {
         this.expandAllDiffs();
       }
-    },
+    }
 
     _openCursorFile() {
       const diff = this.$.diffCursor.getTargetDiffElement();
       Gerrit.Nav.navigateToDiff(this.change, diff.path,
           diff.patchRange.patchNum, this.patchRange.basePatchNum);
-    },
+    }
 
     /**
      * @param {number=} opt_index
@@ -754,7 +766,7 @@
       Gerrit.Nav.navigateToDiff(this.change,
           this._files[this.$.fileCursor.index].__path, this.patchRange.patchNum,
           this.patchRange.basePatchNum);
-    },
+    }
 
     _addDraftAtTarget() {
       const diff = this.$.diffCursor.getTargetDiffElement();
@@ -762,20 +774,20 @@
       if (diff && target) {
         diff.addDraftAtLine(target);
       }
-    },
+    }
 
     _shouldHideChangeTotals(_patchChange) {
       return _patchChange.inserted === 0 && _patchChange.deleted === 0;
-    },
+    }
 
     _shouldHideBinaryChangeTotals(_patchChange) {
       return _patchChange.size_delta_inserted === 0 &&
           _patchChange.size_delta_deleted === 0;
-    },
+    }
 
     _computeFileStatus(status) {
       return status || 'M';
-    },
+    }
 
     _computeDiffURL(change, patchNum, basePatchNum, path, editMode) {
       // Polymer 2: check for undefined
@@ -790,7 +802,7 @@
             basePatchNum);
       }
       return Gerrit.Nav.getUrlForDiff(change, path, patchNum, basePatchNum);
-    },
+    }
 
     _formatBytes(bytes) {
       if (bytes == 0) return '+/-0 B';
@@ -802,7 +814,7 @@
       const prepend = bytes > 0 ? '+' : '';
       return prepend + parseFloat((bytes / Math.pow(bits, exponent))
           .toFixed(decimals)) + ' ' + sizes[exponent];
-    },
+    }
 
     _formatPercentage(size, delta) {
       const oldSize = size - delta;
@@ -811,12 +823,12 @@
 
       const percentage = Math.round(Math.abs(delta * 100 / oldSize));
       return '(' + (delta > 0 ? '+' : '-') + percentage + '%)';
-    },
+    }
 
     _computeBinaryClass(delta) {
       if (delta === 0) { return; }
       return delta >= 0 ? 'added' : 'removed';
-    },
+    }
 
     /**
      * @param {string} baseClass
@@ -831,16 +843,16 @@
         classes.push('invisible');
       }
       return classes.join(' ');
-    },
+    }
 
     _computePathClass(path, expandedFilesRecord) {
       return this._isFileExpanded(path, expandedFilesRecord) ? 'expanded' : '';
-    },
+    }
 
     _computeShowHideIcon(path, expandedFilesRecord) {
       return this._isFileExpanded(path, expandedFilesRecord) ?
         'gr-icons:expand-less' : 'gr-icons:expand-more';
-    },
+    }
 
     _computeFiles(filesByPath, changeComments, patchRange, reviewed, loading) {
       // Polymer 2: check for undefined
@@ -870,7 +882,7 @@
       }
 
       this._files = this._normalizeChangeFilesResponse(files);
-    },
+    }
 
     _computeFilesShown(numFilesShown, files) {
       // Polymer 2: check for undefined
@@ -894,13 +906,13 @@
           Math.max(0, filesShown.length - previousNumFilesShown);
 
       return filesShown;
-    },
+    }
 
     _updateDiffCursor() {
       // Overwrite the cursor's list of diffs:
       this.$.diffCursor.splice(
           ...['diffs', 0, this.$.diffCursor.diffs.length].concat(this.diffs));
-    },
+    }
 
     _filesChanged() {
       if (this._files && this._files.length > 0) {
@@ -910,41 +922,41 @@
         this.$.fileCursor.stops = files;
         this.$.fileCursor.setCursorAtIndex(this.selectedIndex, true);
       }
-    },
+    }
 
     _incrementNumFilesShown() {
       this.numFilesShown += this.fileListIncrement;
-    },
+    }
 
     _computeFileListControlClass(numFilesShown, files) {
       return numFilesShown >= files.length ? 'invisible' : '';
-    },
+    }
 
     _computeIncrementText(numFilesShown, files) {
       if (!files) { return ''; }
       const text =
           Math.min(this.fileListIncrement, files.length - numFilesShown);
       return 'Show ' + text + ' more';
-    },
+    }
 
     _computeShowAllText(files) {
       if (!files) { return ''; }
       return 'Show all ' + files.length + ' files';
-    },
+    }
 
     _computeWarnShowAll(files) {
       return files.length > WARN_SHOW_ALL_THRESHOLD;
-    },
+    }
 
     _computeShowAllWarning(files) {
       if (!this._computeWarnShowAll(files)) { return ''; }
       return 'Warning: showing all ' + files.length +
           ' files may take several seconds.';
-    },
+    }
 
     _showAllFiles() {
       this.numFilesShown = this._files.length;
-    },
+    }
 
     _computePatchSetDescription(revisions, patchNum) {
       // Polymer 2: check for undefined
@@ -955,7 +967,7 @@
       const rev = this.getRevisionByPatchNum(revisions, patchNum);
       return (rev && rev.description) ?
         rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
-    },
+    }
 
     /**
      * Get a descriptive label for use in the status indicator's tooltip and
@@ -967,16 +979,16 @@
       const statusCode = this._computeFileStatus(status);
       return FileStatus.hasOwnProperty(statusCode) ?
         FileStatus[statusCode] : 'Status Unknown';
-    },
+    }
 
     _isFileExpanded(path, expandedFilesRecord) {
       return expandedFilesRecord.base.includes(path);
-    },
+    }
 
     _onLineSelected(e, detail) {
       this.$.diffCursor.moveToLineNumber(detail.number, detail.side,
           detail.path);
-    },
+    }
 
     _computeExpandedFiles(expandedCount, totalCount) {
       if (expandedCount === 0) {
@@ -985,7 +997,7 @@
         return GrFileListConstants.FilesExpandedState.ALL;
       }
       return GrFileListConstants.FilesExpandedState.SOME;
-    },
+    }
 
     /**
      * Handle splices to the list of expanded file paths. If there are any new
@@ -1023,14 +1035,14 @@
 
       this._updateDiffCursor();
       this.$.diffCursor.handleDiffUpdate();
-    },
+    }
 
     _clearCollapsedDiffs(collapsedDiffs) {
       for (const diff of collapsedDiffs) {
         diff.cancel();
         diff.clearDiffContent();
       }
-    },
+    }
 
     /**
      * Given an array of paths and a NodeList of diff elements, render the diff
@@ -1071,13 +1083,13 @@
           this.$.diffCursor.handleDiffUpdate();
         });
       });
-    },
+    }
 
     /** Cancel the rendering work of every diff in the list */
     _cancelDiffs() {
       if (this._cancelForEachDiff) { this._cancelForEachDiff(); }
       this._forEachDiff(d => d.cancel());
-    },
+    }
 
     /**
      * In the given NodeList of diff elements, find the diff for the given path.
@@ -1091,7 +1103,7 @@
           return diffElements[i];
         }
       }
-    },
+    }
 
     /**
      * Reset the comments of a modified thread
@@ -1128,14 +1140,14 @@
       });
       Polymer.dom.flush();
       return;
-    },
+    }
 
     _handleEscKey(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
           this.modifierPressed(e)) { return; }
       e.preventDefault();
       this._displayLine = false;
-    },
+    }
 
     /**
      * Update the loading class for the file list rows. The update is inside a
@@ -1149,19 +1161,19 @@
         // this way, the gray loading style is not shown on initial loads.
         this.classList.toggle('loading', loading && !!this._files.length);
       }, LOADING_DEBOUNCE_INTERVAL);
-    },
+    }
 
     _editModeChanged(editMode) {
       this.classList.toggle('editMode', editMode);
-    },
+    }
 
     _computeReviewedClass(isReviewed) {
       return isReviewed ? 'isReviewed' : '';
-    },
+    }
 
     _computeReviewedText(isReviewed) {
       return isReviewed ? 'MARK UNREVIEWED' : 'MARK REVIEWED';
-    },
+    }
 
     /**
      * Given a file path, return whether that path should have visible size bars
@@ -1171,7 +1183,7 @@
      */
     _showBarsForPath(path) {
       return path !== this.COMMIT_MESSAGE_PATH && path !== this.MERGE_LIST_PATH;
-    },
+    }
 
     /**
      * Compute size bar layout values from the file list.
@@ -1205,7 +1217,7 @@
         stats.deletionOffset = stats.maxAdditionWidth + SIZE_BAR_GAP_WIDTH;
       }
       return stats;
-    },
+    }
 
     /**
      * Get the width of the addition bar for a file.
@@ -1222,7 +1234,7 @@
       const width =
           stats.maxAdditionWidth * file.lines_inserted / stats.maxInserted;
       return width === 0 ? 0 : Math.max(SIZE_BAR_MIN_WIDTH, width);
-    },
+    }
 
     /**
      * Get the x-offset of the addition bar for a file.
@@ -1233,7 +1245,7 @@
     _computeBarAdditionX(file, stats) {
       return stats.maxAdditionWidth -
           this._computeBarAdditionWidth(file, stats);
-    },
+    }
 
     /**
      * Get the width of the deletion bar for a file.
@@ -1250,7 +1262,7 @@
       const width =
           stats.maxDeletionWidth * file.lines_deleted / stats.maxDeleted;
       return width === 0 ? 0 : Math.max(SIZE_BAR_MIN_WIDTH, width);
-    },
+    }
 
     /**
      * Get the x-offset of the deletion bar for a file.
@@ -1259,11 +1271,11 @@
      */
     _computeBarDeletionX(stats) {
       return stats.deletionOffset;
-    },
+    }
 
     _computeShowSizeBars(userPrefs) {
       return !!userPrefs.size_bar_in_change_table;
-    },
+    }
 
     _computeSizeBarsClass(showSizeBars, path) {
       let hideClass = '';
@@ -1273,7 +1285,7 @@
         hideClass = 'invisible';
       }
       return `sizeBars desktop ${hideClass}`;
-    },
+    }
 
     /**
      * Shows registered dynamic columns iff the 'header', 'content' and
@@ -1286,7 +1298,7 @@
       return headerEndpoints && contentEndpoints && summaryEndpoints &&
              headerEndpoints.length === contentEndpoints.length &&
              headerEndpoints.length === summaryEndpoints.length;
-    },
+    }
 
     /**
      * Returns true if none of the inline diffs have been expanded.
@@ -1294,7 +1306,7 @@
      */
     _noDiffsExpanded() {
       return this.filesExpanded === GrFileListConstants.FilesExpandedState.NONE;
-    },
+    }
 
     /**
      * Method to call via binding when each file list row is rendered. This
@@ -1311,7 +1323,7 @@
         }, 1);
       }
       return '';
-    },
+    }
 
     _reviewedTitle(reviewed) {
       if (reviewed) {
@@ -1319,12 +1331,14 @@
       }
 
       return 'Mark as reviewed (shortcut: r)';
-    },
+    }
 
     _handleReloadingDiffPreference() {
       this._getDiffPreferences().then(prefs => {
         this.diffPrefs = prefs;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrFileList.is, GrFileList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index 4c102a2..0d25846 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-file-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -647,9 +647,10 @@
         assert.equal(element.$.fileCursor.index, 0);
         assert.equal(element.selectedIndex, 0);
 
-        sandbox.stub(element, '_addDraftAtTarget');
+        const createCommentInPlaceStub = sandbox.stub(element.$.diffCursor,
+            'createCommentInPlace');
         MockInteractions.pressAndReleaseKeyOn(element, 67, null, 'c');
-        assert.isTrue(element._addDraftAtTarget.called);
+        assert.isTrue(createCommentInPlaceStub.called);
       });
 
       test('i key shows/hides selected inline diff', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html
index 5998264..7a6aa7f 100644
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.html
@@ -19,6 +19,7 @@
 <link rel="import" href="/bower_components/iron-input/iron-input.html">
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-included-in-dialog">
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js
index 4b8ce22..f0cba0b 100644
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.js
@@ -17,36 +17,40 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-included-in-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrIncludedInDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-included-in-dialog'; }
     /**
      * Fired when the user presses the close button.
      *
      * @event close
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      changeNum: {
-        type: Object,
-        observer: '_resetData',
-      },
-      /** @type {?} */
-      _includedIn: Object,
-      _loaded: {
-        type: Boolean,
-        value: false,
-      },
-      _filterText: {
-        type: String,
-        value: '',
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+        changeNum: {
+          type: Object,
+          observer: '_resetData',
+        },
+        /** @type {?} */
+        _includedIn: Object,
+        _loaded: {
+          type: Boolean,
+          value: false,
+        },
+        _filterText: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     loadData() {
       if (!this.changeNum) { return; }
@@ -57,12 +61,12 @@
             this._includedIn = configs;
             this._loaded = true;
           });
-    },
+    }
 
     _resetData() {
       this._includedIn = null;
       this._loaded = false;
-    },
+    }
 
     _computeGroups(includedIn, filterText) {
       if (!includedIn) { return []; }
@@ -83,22 +87,24 @@
         }
       }
       return groups.filter(g => g.items.length);
-    },
+    }
 
     _handleCloseTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('close', null, {bubbles: false});
-    },
+    }
 
     _computeLoadingClass(loaded) {
       return loaded ? 'loading loaded' : 'loading';
-    },
+    }
 
     _onFilterChanged() {
       this.debounce('filter-change', () => {
         this._filterText = this.$.filterInput.bindValue;
       }, 100);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrIncludedInDialog.is, GrIncludedInDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
index 68c77e6..b97e0b4 100644
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-included-in-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.html b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.html
index 220546b..46fd227 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.html
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.html
@@ -23,7 +23,9 @@
 
 <dom-module id="gr-label-score-row">
   <template>
-    <style include="gr-voting-styles"></style>
+    <style include="gr-voting-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       .labelContainer {
         align-items: center;
@@ -109,7 +111,7 @@
         </template>
         <iron-selector
             id="labelSelector"
-            attr-for-selected="value"
+            attr-for-selected="data-value"
             selected="[[_computeLabelValue(labels, permittedLabels, label)]]"
             hidden$="[[!_computeAnyPermittedLabelValues(permittedLabels, label.name)]]"
             on-selected-item-changed="_setSelectedValueText">
@@ -119,8 +121,8 @@
             <gr-button
                 class$="[[_computeButtonClass(value, index, _items.length)]]"
                 has-tooltip
-                name="[[label.name]]"
-                value$="[[value]]"
+                data-name$="[[label.name]]"
+                data-value$="[[value]]"
                 title$="[[_computeLabelValueTitle(labels, label.name, value)]]">
               [[value]]</gr-button>
           </template>
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
index 76e6e64..abfe469 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row.js
@@ -17,56 +17,59 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-label-score-row',
-
+  class GrLabelScoreRow extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-label-score-row'; }
     /**
      * Fired when any label is changed.
      *
      * @event labels-changed
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * @type {{ name: string }}
        */
-      label: Object,
-      labels: Object,
-      name: {
-        type: String,
-        reflectToAttribute: true,
-      },
-      permittedLabels: Object,
-      labelValues: Object,
-      _selectedValueText: {
-        type: String,
-        value: 'No value selected',
-      },
-      _items: {
-        type: Array,
-        computed: '_computePermittedLabelValues(permittedLabels, label.name)',
-      },
-    },
+        label: Object,
+        labels: Object,
+        name: {
+          type: String,
+          reflectToAttribute: true,
+        },
+        permittedLabels: Object,
+        labelValues: Object,
+        _selectedValueText: {
+          type: String,
+          value: 'No value selected',
+        },
+        _items: {
+          type: Array,
+          computed: '_computePermittedLabelValues(permittedLabels, label.name)',
+        },
+      };
+    }
 
     get selectedItem() {
       if (!this._ironSelector) { return undefined; }
       return this._ironSelector.selectedItem;
-    },
+    }
 
     get selectedValue() {
       if (!this._ironSelector) { return undefined; }
       return this._ironSelector.selected;
-    },
+    }
 
     setSelectedValue(value) {
       // The selector may not be present if it’s not at the latest patch set.
       if (!this._ironSelector) { return; }
       this._ironSelector.select(value);
-    },
+    }
 
     get _ironSelector() {
       return this.$ && this.$.labelSelector;
-    },
+    }
 
     _computeBlankItems(permittedLabels, label, side) {
       if (!permittedLabels || !permittedLabels[label] ||
@@ -82,7 +85,7 @@
       const endPosition = this.labelValues[parseInt(
           permittedLabels[label][permittedLabels[label].length - 1], 10)];
       return new Array(Object.keys(this.labelValues).length - endPosition - 1);
-    },
+    }
 
     _getLabelValue(labels, permittedLabels, label) {
       if (label.value) {
@@ -93,7 +96,7 @@
         return permittedLabels[label.name].find(
             value => parseInt(value, 10) === labels[label.name].default_value);
       }
-    },
+    }
 
     _computeButtonClass(value, index, totalItems) {
       const classes = [];
@@ -114,7 +117,7 @@
       }
 
       return classes.join(' ');
-    },
+    }
 
     _computeLabelValue(labels, permittedLabels, label) {
       if ([labels, permittedLabels, label].some(arg => arg === undefined)) {
@@ -131,7 +134,7 @@
         }
       }
       return null;
-    },
+    }
 
     _setSelectedValueText(e) {
       // Needed because when the selected item changes, it first changes to
@@ -140,22 +143,22 @@
       this._selectedValueText = e.target.selectedItem.getAttribute('title');
       // Needed to update the style of the selected button.
       this.updateStyles();
-      const name = e.target.selectedItem.name;
-      const value = e.target.selectedItem.getAttribute('value');
+      const name = e.target.selectedItem.dataset.name;
+      const value = e.target.selectedItem.dataset.value;
       this.dispatchEvent(new CustomEvent(
           'labels-changed',
           {detail: {name, value}, bubbles: true, composed: true}));
-    },
+    }
 
     _computeAnyPermittedLabelValues(permittedLabels, label) {
       return permittedLabels && permittedLabels.hasOwnProperty(label) &&
         permittedLabels[label].length;
-    },
+    }
 
     _computeHiddenClass(permittedLabels, label) {
       return !this._computeAnyPermittedLabelValues(permittedLabels, label) ?
         'hidden' : '';
-    },
+    }
 
     _computePermittedLabelValues(permittedLabels, label) {
       // Polymer 2: check for undefined
@@ -164,12 +167,14 @@
       }
 
       return permittedLabels[label];
-    },
+    }
 
     _computeLabelValueTitle(labels, label, value) {
       return labels[label] &&
         labels[label].values &&
         labels[label].values[value];
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLabelScoreRow.is, GrLabelScoreRow);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
index 519fbb8..e9c21bc 100644
--- a/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
+++ b/polygerrit-ui/app/elements/change/gr-label-score-row/gr-label-score-row_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-label-score-row</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -110,7 +110,7 @@
       element.addEventListener('labels-changed', labelsChangedHandler);
       assert.ok(element.$.labelSelector);
       MockInteractions.tap(element.$$(
-          'gr-button[value="-1"]'));
+          'gr-button[data-value="-1"]'));
       flushAsynchronousOperations();
       assert.strictEqual(element.selectedValue, '-1');
       assert.strictEqual(element.selectedItem
@@ -167,7 +167,7 @@
 
     test('do not display tooltips on touch devices', () => {
       const verifiedBtn = element.$$(
-          'iron-selector > gr-button[value="-1"]');
+          'iron-selector > gr-button[data-value="-1"]');
 
       // On touch devices, tooltips should not be shown.
       verifiedBtn._isTouchDevice = true;
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
index 5b498c2..2c164f1 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.js
@@ -17,22 +17,29 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-label-scores',
+  class GrLabelScores extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-label-scores'; }
 
-    properties: {
-      _labels: {
-        type: Array,
-        computed: '_computeLabels(change.labels.*, account)',
-      },
-      permittedLabels: {
-        type: Object,
-        observer: '_computeColumns',
-      },
-      /** @type {?} */
-      change: Object,
-      _labelValues: Object,
-    },
+    static get properties() {
+      return {
+        _labels: {
+          type: Array,
+          computed: '_computeLabels(change.labels.*, account)',
+        },
+        permittedLabels: {
+          type: Object,
+          observer: '_computeColumns',
+        },
+        /** @type {?} */
+        change: Object,
+        /** @type {?} */
+        account: Object,
+
+        _labelValues: Object,
+      };
+    }
 
     getLabelValues() {
       const labels = {};
@@ -58,7 +65,7 @@
         }
       }
       return labels;
-    },
+    }
 
     _getStringLabelValue(labels, labelName, numberValue) {
       for (const k in labels[labelName].values) {
@@ -67,7 +74,7 @@
         }
       }
       return numberValue;
-    },
+    }
 
     _getVoteForAccount(labels, labelName, account) {
       const votes = labels[labelName];
@@ -80,7 +87,7 @@
         }
       }
       return null;
-    },
+    }
 
     _computeLabels(labelRecord, account) {
       // Polymer 2: check for undefined
@@ -96,7 +103,7 @@
           value: this._getVoteForAccount(labelsObj, key, this.account),
         };
       });
-    },
+    }
 
     _computeColumns(permittedLabels) {
       const labels = Object.keys(permittedLabels);
@@ -115,11 +122,11 @@
         values[orderedValues[i]] = i;
       }
       this._labelValues = values;
-    },
+    }
 
     _changeIsMerged(changeStatus) {
       return changeStatus === 'MERGED';
-    },
+    }
 
     /**
      * @param label {string|undefined}
@@ -133,6 +140,8 @@
 
       return permittedLabels.hasOwnProperty(label) &&
         permittedLabels[label].length ? 'access' : 'no-access';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLabelScores.is, GrLabelScores);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html
index b8d471c..4c489b7 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-label-scores</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.html b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
index acbee7f..fbd5d68d 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
@@ -19,6 +19,7 @@
 <link rel="import" href="/bower_components/iron-icon/iron-icon.html">
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../shared/gr-account-label/gr-account-label.html">
+<link rel="import" href="../../shared/gr-account-chip/gr-account-chip.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
 <link rel="import" href="../../shared/gr-formatted-text/gr-formatted-text.html">
@@ -30,7 +31,9 @@
 
 <dom-module id="gr-message">
   <template>
-    <style include="gr-voting-styles"></style>
+    <style include="gr-voting-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       :host {
         border-bottom: 1px solid var(--border-color);
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index 26e0cd3..7c1d66c 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -20,9 +20,15 @@
   const PATCH_SET_PREFIX_PATTERN = /^Patch Set \d+: /;
   const LABEL_TITLE_SCORE_PATTERN = /^([A-Za-z0-9-]+)([+-]\d+)$/;
 
-  Polymer({
-    is: 'gr-message',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrMessage extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-message'; }
     /**
      * Fired when this message's reply link is tapped.
      *
@@ -35,90 +41,93 @@
      * @event message-anchor-tap
      */
 
-    listeners: {
-      click: '_handleClick',
-    },
+    static get properties() {
+      return {
+        changeNum: Number,
+        /** @type {?} */
+        message: Object,
+        author: {
+          type: Object,
+          computed: '_computeAuthor(message)',
+        },
+        comments: {
+          type: Object,
+          observer: '_commentsChanged',
+        },
+        config: Object,
+        hideAutomated: {
+          type: Boolean,
+          value: false,
+        },
+        hidden: {
+          type: Boolean,
+          computed: '_computeIsHidden(hideAutomated, isAutomated)',
+          reflectToAttribute: true,
+        },
+        isAutomated: {
+          type: Boolean,
+          computed: '_computeIsAutomated(message)',
+        },
+        showAvatar: {
+          type: Boolean,
+          computed: '_computeShowAvatar(author, config)',
+        },
+        showOnBehalfOf: {
+          type: Boolean,
+          computed: '_computeShowOnBehalfOf(message)',
+        },
+        showReplyButton: {
+          type: Boolean,
+          computed: '_computeShowReplyButton(message, _loggedIn)',
+        },
+        projectName: {
+          type: String,
+          observer: '_projectNameChanged',
+        },
 
-    properties: {
-      changeNum: Number,
-      /** @type {?} */
-      message: Object,
-      author: {
-        type: Object,
-        computed: '_computeAuthor(message)',
-      },
-      comments: {
-        type: Object,
-        observer: '_commentsChanged',
-      },
-      config: Object,
-      hideAutomated: {
-        type: Boolean,
-        value: false,
-      },
-      hidden: {
-        type: Boolean,
-        computed: '_computeIsHidden(hideAutomated, isAutomated)',
-        reflectToAttribute: true,
-      },
-      isAutomated: {
-        type: Boolean,
-        computed: '_computeIsAutomated(message)',
-      },
-      showAvatar: {
-        type: Boolean,
-        computed: '_computeShowAvatar(author, config)',
-      },
-      showOnBehalfOf: {
-        type: Boolean,
-        computed: '_computeShowOnBehalfOf(message)',
-      },
-      showReplyButton: {
-        type: Boolean,
-        computed: '_computeShowReplyButton(message, _loggedIn)',
-      },
-      projectName: {
-        type: String,
-        observer: '_projectNameChanged',
-      },
-
-      /**
+        /**
        * A mapping from label names to objects representing the minimum and
        * maximum possible values for that label.
        */
-      labelExtremes: Object,
+        labelExtremes: Object,
 
-      /**
+        /**
        * @type {{ commentlinks: Array }}
        */
-      _projectConfig: Object,
-      // Computed property needed to trigger Polymer value observing.
-      _expanded: {
-        type: Object,
-        computed: '_computeExpanded(message.expanded)',
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _projectConfig: Object,
+        // Computed property needed to trigger Polymer value observing.
+        _expanded: {
+          type: Object,
+          computed: '_computeExpanded(message.expanded)',
+        },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get observers() {
+      return [
+        '_updateExpandedClass(message.expanded)',
+      ];
+    }
 
-    observers: [
-      '_updateExpandedClass(message.expanded)',
-    ],
+    created() {
+      super.created();
+      this.addEventListener('click',
+          e => this._handleClick(e));
+    }
 
     ready() {
+      super.ready();
       this.$.restAPI.getConfig().then(config => {
         this.config = config;
       });
       this.$.restAPI.getLoggedIn().then(loggedIn => {
         this._loggedIn = loggedIn;
       });
-    },
+    }
 
     _updateExpandedClass(expanded) {
       if (expanded) {
@@ -126,30 +135,30 @@
       } else {
         this.classList.remove('expanded');
       }
-    },
+    }
 
     _computeAuthor(message) {
       return message.author || message.updated_by;
-    },
+    }
 
     _computeShowAvatar(author, config) {
       return !!(author && config && config.plugin && config.plugin.has_avatars);
-    },
+    }
 
     _computeShowOnBehalfOf(message) {
       const author = message.author || message.updated_by;
       return !!(author && message.real_author &&
           author._account_id != message.real_author._account_id);
-    },
+    }
 
     _computeShowReplyButton(message, loggedIn) {
       return message && !!message.message && loggedIn &&
           !this._computeIsAutomated(message);
-    },
+    }
 
     _computeExpanded(expanded) {
       return expanded;
-    },
+    }
 
     /**
      * If there is no value set on the message object as to whether _expanded
@@ -160,33 +169,33 @@
       if (this.message && this.message.expanded === undefined) {
         this.set('message.expanded', Object.keys(value || {}).length > 0);
       }
-    },
+    }
 
     _handleClick(e) {
       if (this.message.expanded) { return; }
       e.stopPropagation();
       this.set('message.expanded', true);
-    },
+    }
 
     _handleAuthorClick(e) {
       if (!this.message.expanded) { return; }
       e.stopPropagation();
       this.set('message.expanded', false);
-    },
+    }
 
     _computeIsAutomated(message) {
       return !!(message.reviewer ||
           this._computeIsReviewerUpdate(message) ||
           (message.tag && message.tag.startsWith('autogenerated')));
-    },
+    }
 
     _computeIsHidden(hideAutomated, isAutomated) {
       return hideAutomated && isAutomated;
-    },
+    }
 
     _computeIsReviewerUpdate(event) {
       return event.type === 'REVIEWER_UPDATE';
-    },
+    }
 
     _getScores(message) {
       if (!message.message) { return []; }
@@ -199,7 +208,7 @@
           .map(s => s.match(LABEL_TITLE_SCORE_PATTERN))
           .filter(ms => ms && ms.length === 3)
           .map(ms => ({label: ms[1], value: ms[2]}));
-    },
+    }
 
     _computeScoreClass(score, labelExtremes) {
       // Polymer 2: check for undefined
@@ -222,14 +231,14 @@
         }
       }
       return classes.join(' ');
-    },
+    }
 
     _computeClass(expanded, showAvatar, message) {
       const classes = [];
       classes.push(expanded ? 'expanded' : 'collapsed');
       classes.push(showAvatar ? 'showAvatar' : 'hideAvatar');
       return classes.join(' ');
-    },
+    }
 
     _handleAnchorClick(e) {
       e.preventDefault();
@@ -238,26 +247,28 @@
         composed: true,
         detail: {id: this.message.id},
       }));
-    },
+    }
 
     _handleReplyTap(e) {
       e.preventDefault();
       this.fire('reply', {message: this.message});
-    },
+    }
 
     _projectNameChanged(name) {
       this.$.restAPI.getProjectConfig(name).then(config => {
         this._projectConfig = config;
       });
-    },
+    }
 
     _computeExpandToggleIcon(expanded) {
       return expanded ? 'gr-icons:expand-less' : 'gr-icons:expand-more';
-    },
+    }
 
     _toggleExpanded(e) {
       e.stopPropagation();
       this.set('message.expanded', !this.message.expanded);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrMessage.is, GrMessage);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
index ef5a756..01bc691 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-message</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
index d90132d..92e7cce 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
@@ -25,57 +25,61 @@
     SHOW_MORE: 'show-more-messages',
   };
 
-  Polymer({
-    is: 'gr-messages-list',
+  class GrMessagesList extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-messages-list'; }
 
-    properties: {
-      changeNum: Number,
-      messages: {
-        type: Array,
-        value() { return []; },
-      },
-      reviewerUpdates: {
-        type: Array,
-        value() { return []; },
-      },
-      changeComments: Object,
-      projectName: String,
-      showReplyButtons: {
-        type: Boolean,
-        value: false,
-      },
-      labels: Object,
+    static get properties() {
+      return {
+        changeNum: Number,
+        messages: {
+          type: Array,
+          value() { return []; },
+        },
+        reviewerUpdates: {
+          type: Array,
+          value() { return []; },
+        },
+        changeComments: Object,
+        projectName: String,
+        showReplyButtons: {
+          type: Boolean,
+          value: false,
+        },
+        labels: Object,
 
-      _expanded: {
-        type: Boolean,
-        value: false,
-        observer: '_expandedChanged',
-      },
-      _hideAutomated: {
-        type: Boolean,
-        value: false,
-      },
-      /**
+        _expanded: {
+          type: Boolean,
+          value: false,
+          observer: '_expandedChanged',
+        },
+        _hideAutomated: {
+          type: Boolean,
+          value: false,
+        },
+        /**
        * The messages after processing and including merged reviewer updates.
        */
-      _processedMessages: {
-        type: Array,
-        computed: '_computeItems(messages, reviewerUpdates)',
-        observer: '_processedMessagesChanged',
-      },
-      /**
+        _processedMessages: {
+          type: Array,
+          computed: '_computeItems(messages, reviewerUpdates)',
+          observer: '_processedMessagesChanged',
+        },
+        /**
        * The subset of _processedMessages that is visible to the user.
        */
-      _visibleMessages: {
-        type: Array,
-        value() { return []; },
-      },
+        _visibleMessages: {
+          type: Array,
+          value() { return []; },
+        },
 
-      _labelExtremes: {
-        type: Object,
-        computed: '_computeLabelExtremes(labels.*)',
-      },
-    },
+        _labelExtremes: {
+          type: Object,
+          computed: '_computeLabelExtremes(labels.*)',
+        },
+      };
+    }
 
     scrollToMessage(messageID) {
       let el = this.$$('[data-message-id="' + messageID + '"]');
@@ -108,12 +112,12 @@
       }
       window.scrollTo(0, top);
       this._highlightEl(el);
-    },
+    }
 
     _isAutomated(message) {
       return !!(message.reviewer ||
           (message.tag && message.tag.startsWith('autogenerated')));
-    },
+    }
 
     _computeItems(messages, reviewerUpdates) {
       // Polymer 2: check for undefined
@@ -152,7 +156,7 @@
         }
       }
       return result;
-    },
+    }
 
     _expandedChanged(exp) {
       if (this._processedMessages) {
@@ -169,7 +173,7 @@
           this.notifyPath(`_visibleMessages.${i}.expanded`);
         }
       }
-    },
+    }
 
     _highlightEl(el) {
       const highlightedEls =
@@ -183,23 +187,23 @@
       }
       el.addEventListener('animationend', handleAnimationEnd);
       el.classList.add('highlighted');
-    },
+    }
 
     /**
      * @param {boolean} expand
      */
     handleExpandCollapse(expand) {
       this._expanded = expand;
-    },
+    }
 
     _handleExpandCollapseTap(e) {
       e.preventDefault();
       this.handleExpandCollapse(!this._expanded);
-    },
+    }
 
     _handleAnchorClick(e) {
       this.scrollToMessage(e.detail.id);
-    },
+    }
 
     _hasAutomatedMessages(messages) {
       if (!messages) { return false; }
@@ -209,11 +213,11 @@
         }
       }
       return false;
-    },
+    }
 
     _computeExpandCollapseMessage(expanded) {
       return expanded ? 'Collapse all' : 'Expand all';
-    },
+    }
 
     /**
      * Computes message author's file comments for change's message.
@@ -268,7 +272,7 @@
         }
       }
       return msgComments;
-    },
+    }
 
     /**
      * Returns the number of messages to splice to the beginning of
@@ -293,7 +297,7 @@
         delta = msgsRemaining - i;
       }
       return Math.min(msgsRemaining, delta);
-    },
+    }
 
     /**
      * Gets the number of messages that would be visible, but do not currently
@@ -309,20 +313,20 @@
             this._getHumanMessages(visibleMessages).length;
       }
       return messages.length - visibleMessages.length;
-    },
+    }
 
     _computeIncrementText(visibleMessages, messages, hideAutomated) {
       let delta = this._getDelta(visibleMessages, messages, hideAutomated);
       delta = Math.min(
           this._numRemaining(visibleMessages, messages, hideAutomated), delta);
       return 'Show ' + Math.min(MESSAGES_INCREMENT, delta) + ' more';
-    },
+    }
 
     _getHumanMessages(messages) {
       return messages.filter(msg => {
         return !this._isAutomated(msg);
       });
-    },
+    }
 
     _computeShowHideTextHidden(visibleMessages, messages,
         hideAutomated) {
@@ -335,12 +339,12 @@
         visibleMessages = this._getHumanMessages(visibleMessages);
       }
       return visibleMessages.length >= messages.length;
-    },
+    }
 
     _handleShowAllTap() {
       this._visibleMessages = this._processedMessages;
       this.$.reporting.reportInteraction(ReportingEvent.SHOW_ALL);
-    },
+    }
 
     _handleIncrementShownMessages() {
       const delta = this._getDelta(this._visibleMessages,
@@ -350,27 +354,27 @@
       // Add newMessages to the beginning of _visibleMessages
       this.splice(...['_visibleMessages', 0, 0].concat(newMessages));
       this.$.reporting.reportInteraction(ReportingEvent.SHOW_MORE);
-    },
+    }
 
     _processedMessagesChanged(messages) {
       if (messages) {
         this._visibleMessages = messages.slice(-MAX_INITIAL_SHOWN_MESSAGES);
       }
-    },
+    }
 
     _computeNumMessagesText(visibleMessages, messages,
         hideAutomated) {
       const total =
           this._numRemaining(visibleMessages, messages, hideAutomated);
       return total === 1 ? 'Show 1 message' : 'Show all ' + total + ' messages';
-    },
+    }
 
     _computeIncrementHidden(visibleMessages, messages,
         hideAutomated) {
       const total =
           this._numRemaining(visibleMessages, messages, hideAutomated);
       return total <= this._getDelta(visibleMessages, messages, hideAutomated);
-    },
+    }
 
     /**
      * Compute a mapping from label name to objects representing the minimum and
@@ -389,6 +393,8 @@
         extremes[key] = {min: values[0], max: values[values.length - 1]};
       }
       return extremes;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrMessagesList.is, GrMessagesList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
index 265cee98..9caf13d 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-messages-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
index 18a136e..25a56a9 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.js
@@ -17,9 +17,19 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-related-changes-list',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrRelatedChangesList extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-related-changes-list'; }
     /**
      * Fired when a new section is loaded so that the change view can determine
      * a show more button is needed, sometimes before all the sections finish
@@ -28,64 +38,62 @@
      * @event new-section-loaded
      */
 
-    properties: {
-      change: Object,
-      hasParent: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
-      patchNum: String,
-      parentChange: Object,
-      hidden: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      loading: {
-        type: Boolean,
-        notify: true,
-      },
-      mergeable: Boolean,
-      _connectedRevisions: {
-        type: Array,
-        computed: '_computeConnectedRevisions(change, patchNum, ' +
+    static get properties() {
+      return {
+        change: Object,
+        hasParent: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
+        patchNum: String,
+        parentChange: Object,
+        hidden: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        loading: {
+          type: Boolean,
+          notify: true,
+        },
+        mergeable: Boolean,
+        _connectedRevisions: {
+          type: Array,
+          computed: '_computeConnectedRevisions(change, patchNum, ' +
             '_relatedResponse.changes)',
-      },
-      /** @type {?} */
-      _relatedResponse: {
-        type: Object,
-        value() { return {changes: []}; },
-      },
-      /** @type {?} */
-      _submittedTogether: {
-        type: Object,
-        value() { return {changes: []}; },
-      },
-      _conflicts: {
-        type: Array,
-        value() { return []; },
-      },
-      _cherryPicks: {
-        type: Array,
-        value() { return []; },
-      },
-      _sameTopic: {
-        type: Array,
-        value() { return []; },
-      },
-    },
+        },
+        /** @type {?} */
+        _relatedResponse: {
+          type: Object,
+          value() { return {changes: []}; },
+        },
+        /** @type {?} */
+        _submittedTogether: {
+          type: Object,
+          value() { return {changes: []}; },
+        },
+        _conflicts: {
+          type: Array,
+          value() { return []; },
+        },
+        _cherryPicks: {
+          type: Array,
+          value() { return []; },
+        },
+        _sameTopic: {
+          type: Array,
+          value() { return []; },
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
-
-    observers: [
-      '_resultsChanged(_relatedResponse, _submittedTogether, ' +
+    static get observers() {
+      return [
+        '_resultsChanged(_relatedResponse, _submittedTogether, ' +
           '_conflicts, _cherryPicks, _sameTopic)',
-    ],
+      ];
+    }
 
     clear() {
       this.loading = true;
@@ -96,7 +104,7 @@
       this._conflicts = [];
       this._cherryPicks = [];
       this._sameTopic = [];
-    },
+    }
 
     reload() {
       if (!this.change || !this.patchNum) {
@@ -144,7 +152,7 @@
       return Promise.all(promises).then(() => {
         this.loading = false;
       });
-    },
+    }
 
     _fireReloadEvent() {
       // The listener on the change computes height of the related changes
@@ -152,7 +160,7 @@
       // that requires a flush.
       Polymer.dom.flush();
       this.dispatchEvent(new CustomEvent('new-section-loaded'));
-    },
+    }
 
     /**
      * Determines whether or not the given change has a parent change. If there
@@ -166,34 +174,34 @@
       return relatedChanges.length > 0 &&
           relatedChanges[relatedChanges.length - 1].change_id !==
           currentChangeId;
-    },
+    }
 
     _getRelatedChanges() {
       return this.$.restAPI.getRelatedChanges(this.change._number,
           this.patchNum);
-    },
+    }
 
     _getSubmittedTogether() {
       return this.$.restAPI.getChangesSubmittedTogether(this.change._number);
-    },
+    }
 
     _getServerConfig() {
       return this.$.restAPI.getConfig();
-    },
+    }
 
     _getConflicts() {
       return this.$.restAPI.getChangeConflicts(this.change._number);
-    },
+    }
 
     _getCherryPicks() {
       return this.$.restAPI.getChangeCherryPicks(this.change.project,
           this.change.change_id, this.change._number);
-    },
+    }
 
     _getChangesWithSameTopic() {
       return this.$.restAPI.getChangesWithSameTopic(this.change.topic,
           this.change._number);
-    },
+    }
 
     /**
      * @param {number} changeNum
@@ -203,7 +211,7 @@
      */
     _computeChangeURL(changeNum, project, opt_patchNum) {
       return Gerrit.Nav.getUrlForChangeById(changeNum, project, opt_patchNum);
-    },
+    }
 
     _computeChangeContainerClass(currentChange, relatedChange) {
       const classes = ['changeContainer'];
@@ -214,7 +222,7 @@
         classes.push('thisChange');
       }
       return classes.join(' ');
-    },
+    }
 
     /**
      * Do the given objects describe the same change? Compares the changes by
@@ -229,7 +237,7 @@
       const aNum = this._getChangeNumber(a);
       const bNum = this._getChangeNumber(b);
       return aNum === bNum;
-    },
+    }
 
     /**
      * Get the change number from either a ChangeInfo (such as those included in
@@ -251,7 +259,7 @@
         return change._change_number;
       }
       return change._number;
-    },
+    }
 
     _computeLinkClass(change) {
       const statuses = [];
@@ -262,7 +270,7 @@
         statuses.push('submittable');
       }
       return statuses.join(' ');
-    },
+    }
 
     _computeChangeStatusClass(change) {
       const classes = ['status'];
@@ -276,7 +284,7 @@
         classes.push('hidden');
       }
       return classes.join(' ');
-    },
+    }
 
     _computeChangeStatus(change) {
       switch (change.status) {
@@ -293,7 +301,7 @@
         return 'Submittable';
       }
       return '';
-    },
+    }
 
     _resultsChanged(related, submittedTogether, conflicts,
         cherryPicks, sameTopic) {
@@ -323,11 +331,11 @@
         }
       }
       this.hidden = true;
-    },
+    }
 
     _isIndirectAncestor(change) {
       return !this._connectedRevisions.includes(change.commit.commit);
-    },
+    }
 
     _computeConnectedRevisions(change, patchNum, relatedChanges) {
       // Polymer 2: check for undefined
@@ -364,7 +372,7 @@
         --pos;
       }
       return connected;
-    },
+    }
 
     _computeSubmittedTogetherClass(submittedTogether) {
       if (!submittedTogether || (
@@ -373,11 +381,13 @@
         return 'hidden';
       }
       return '';
-    },
+    }
 
     _computeNonVisibleChangesNote(n) {
       const noun = n === 1 ? 'change' : 'changes';
       return `(+ ${n} non-visible ${noun})`;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRelatedChangesList.is, GrRelatedChangesList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html
index f04d40e..38b2fb9 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-related-changes-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html
index 3632348..7d95323 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog-it_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reply-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -156,7 +156,7 @@
             const labelScoreRows = Polymer.dom(element.$.labelScores.root)
                 .querySelector('gr-label-score-row[name="Code-Review"]');
             const selectedBtn = Polymer.dom(labelScoreRows.root)
-                .querySelector('gr-button[value="+1"].iron-selected');
+                .querySelector('gr-button[data-value="+1"].iron-selected');
             assert.isOk(selectedBtn);
             done();
           });
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
index c944bf4..e836ccc 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.html
@@ -35,6 +35,7 @@
 <link rel="import" href="../../shared/gr-account-list/gr-account-list.html">
 <link rel="import" href="../gr-label-scores/gr-label-scores.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../change/gr-comment-list/gr-comment-list.html">
 <script src="../../../scripts/gr-display-name-utils/gr-display-name-utils.js"></script>
 <script src="../../../scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.js"></script>
 
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index b2b1588..eab1c8d 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -52,9 +52,23 @@
 
   const SEND_REPLY_TIMING_LABEL = 'SendReply';
 
-  Polymer({
-    is: 'gr-reply-dialog',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrReplyDialog extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-reply-dialog'; }
     /**
      * Fired when a reply is successfully sent.
      *
@@ -93,156 +107,159 @@
       * @event send-disabled-changed
       */
 
-    properties: {
+    constructor() {
+      super();
+      this.FocusTarget = FocusTarget;
+    }
+
+    static get properties() {
+      return {
       /**
        * @type {{ _number: number, removable_reviewers: Array }}
        */
-      change: Object,
-      patchNum: String,
-      canBeStarted: {
-        type: Boolean,
-        value: false,
-      },
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      draft: {
-        type: String,
-        value: '',
-        observer: '_draftChanged',
-      },
-      quote: {
-        type: String,
-        value: '',
-      },
-      diffDrafts: {
-        type: Object,
-        observer: '_handleHeightChanged',
-      },
-      /** @type {!Function} */
-      filterReviewerSuggestion: {
-        type: Function,
-        value() {
-          return this._filterReviewerSuggestionGenerator(false);
+        change: Object,
+        patchNum: String,
+        canBeStarted: {
+          type: Boolean,
+          value: false,
         },
-      },
-      /** @type {!Function} */
-      filterCCSuggestion: {
-        type: Function,
-        value() {
-          return this._filterReviewerSuggestionGenerator(true);
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
         },
-      },
-      permittedLabels: Object,
-      /**
+        draft: {
+          type: String,
+          value: '',
+          observer: '_draftChanged',
+        },
+        quote: {
+          type: String,
+          value: '',
+        },
+        diffDrafts: {
+          type: Object,
+          observer: '_handleHeightChanged',
+        },
+        /** @type {!Function} */
+        filterReviewerSuggestion: {
+          type: Function,
+          value() {
+            return this._filterReviewerSuggestionGenerator(false);
+          },
+        },
+        /** @type {!Function} */
+        filterCCSuggestion: {
+          type: Function,
+          value() {
+            return this._filterReviewerSuggestionGenerator(true);
+          },
+        },
+        permittedLabels: Object,
+        /**
        * @type {{ commentlinks: Array }}
        */
-      projectConfig: Object,
-      knownLatestState: String,
-      underReview: {
-        type: Boolean,
-        value: true,
-      },
-
-      _account: Object,
-      _ccs: Array,
-      /** @type {?Object} */
-      _ccPendingConfirmation: {
-        type: Object,
-        observer: '_reviewerPendingConfirmationUpdated',
-      },
-      _messagePlaceholder: {
-        type: String,
-        computed: '_computeMessagePlaceholder(canBeStarted)',
-      },
-      _owner: Object,
-      /** @type {?} */
-      _pendingConfirmationDetails: Object,
-      _includeComments: {
-        type: Boolean,
-        value: true,
-      },
-      _reviewers: Array,
-      /** @type {?Object} */
-      _reviewerPendingConfirmation: {
-        type: Object,
-        observer: '_reviewerPendingConfirmationUpdated',
-      },
-      _previewFormatting: {
-        type: Boolean,
-        value: false,
-        observer: '_handleHeightChanged',
-      },
-      _reviewersPendingRemove: {
-        type: Object,
-        value: {
-          CC: [],
-          REVIEWER: [],
+        projectConfig: Object,
+        knownLatestState: String,
+        underReview: {
+          type: Boolean,
+          value: true,
         },
-      },
-      _sendButtonLabel: {
-        type: String,
-        computed: '_computeSendButtonLabel(canBeStarted)',
-      },
-      _savingComments: Boolean,
-      _reviewersMutated: {
-        type: Boolean,
-        value: false,
-      },
-      _labelsChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _saveTooltip: {
-        type: String,
-        value: ButtonTooltips.SAVE,
-        readOnly: true,
-      },
-      _pluginMessage: {
-        type: String,
-        value: '',
-      },
-      _sendDisabled: {
-        type: Boolean,
-        computed: '_computeSendButtonDisabled(_sendButtonLabel, diffDrafts, ' +
-            'draft, _reviewersMutated, _labelsChanged, _includeComments, ' +
-            'disabled)',
-        observer: '_sendDisabledChanged',
-      },
-    },
 
-    FocusTarget,
+        _account: Object,
+        _ccs: Array,
+        /** @type {?Object} */
+        _ccPendingConfirmation: {
+          type: Object,
+          observer: '_reviewerPendingConfirmationUpdated',
+        },
+        _messagePlaceholder: {
+          type: String,
+          computed: '_computeMessagePlaceholder(canBeStarted)',
+        },
+        _owner: Object,
+        /** @type {?} */
+        _pendingConfirmationDetails: Object,
+        _includeComments: {
+          type: Boolean,
+          value: true,
+        },
+        _reviewers: Array,
+        /** @type {?Object} */
+        _reviewerPendingConfirmation: {
+          type: Object,
+          observer: '_reviewerPendingConfirmationUpdated',
+        },
+        _previewFormatting: {
+          type: Boolean,
+          value: false,
+          observer: '_handleHeightChanged',
+        },
+        _reviewersPendingRemove: {
+          type: Object,
+          value: {
+            CC: [],
+            REVIEWER: [],
+          },
+        },
+        _sendButtonLabel: {
+          type: String,
+          computed: '_computeSendButtonLabel(canBeStarted)',
+        },
+        _savingComments: Boolean,
+        _reviewersMutated: {
+          type: Boolean,
+          value: false,
+        },
+        _labelsChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _saveTooltip: {
+          type: String,
+          value: ButtonTooltips.SAVE,
+          readOnly: true,
+        },
+        _pluginMessage: {
+          type: String,
+          value: '',
+        },
+        _sendDisabled: {
+          type: Boolean,
+          computed: '_computeSendButtonDisabled(_sendButtonLabel, ' +
+            'diffDrafts, draft, _reviewersMutated, _labelsChanged, ' +
+            '_includeComments, disabled)',
+          observer: '_sendDisabledChanged',
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
+    get keyBindings() {
+      return {
+        'esc': '_handleEscKey',
+        'ctrl+enter meta+enter': '_handleEnterKey',
+      };
+    }
 
-    keyBindings: {
-      'esc': '_handleEscKey',
-      'ctrl+enter meta+enter': '_handleEnterKey',
-    },
-
-    observers: [
-      '_changeUpdated(change.reviewers.*, change.owner)',
-      '_ccsChanged(_ccs.splices)',
-      '_reviewersChanged(_reviewers.splices)',
-    ],
+    static get observers() {
+      return [
+        '_changeUpdated(change.reviewers.*, change.owner)',
+        '_ccsChanged(_ccs.splices)',
+        '_reviewersChanged(_reviewers.splices)',
+      ];
+    }
 
     attached() {
+      super.attached();
       this._getAccount().then(account => {
         this._account = account || {};
       });
-    },
+    }
 
     ready() {
+      super.ready();
       this.$.jsAPI.addElement(this.$.jsAPI.Element.REPLY_DIALOG, this);
-    },
+    }
 
     open(opt_focusTarget) {
       this.knownLatestState = LatestPatchState.CHECKING;
@@ -268,11 +285,11 @@
           this._savingComments = false;
         });
       }
-    },
+    }
 
     focus() {
       this._focusOn(FocusTarget.ANY);
-    },
+    }
 
     getFocusStops() {
       const end = this._sendDisabled ? this.$.cancelButton : this.$.sendButton;
@@ -280,14 +297,14 @@
         start: this.$.reviewers.focusStart,
         end,
       };
-    },
+    }
 
     setLabelValue(label, value) {
       const selectorEl =
           this.$.labelScores.$$(`gr-label-score-row[name="${label}"]`);
       if (!selectorEl) { return; }
       selectorEl.setSelectedValue(value);
-    },
+    }
 
     getLabelValue(label) {
       const selectorEl =
@@ -295,23 +312,23 @@
       if (!selectorEl) { return null; }
 
       return selectorEl.selectedValue;
-    },
+    }
 
     _handleEscKey(e) {
       this.cancel();
-    },
+    }
 
     _handleEnterKey(e) {
       this._submit();
-    },
+    }
 
     _ccsChanged(splices) {
       this._reviewerTypeChanged(splices, ReviewerTypes.CC);
-    },
+    }
 
     _reviewersChanged(splices) {
       this._reviewerTypeChanged(splices, ReviewerTypes.REVIEWER);
-    },
+    }
 
     _reviewerTypeChanged(splices, reviewerType) {
       if (splices && splices.indexSplices) {
@@ -342,7 +359,7 @@
           }
         }
       }
-    },
+    }
 
     _processReviewerChange(indexSplices, type) {
       for (const splice of indexSplices) {
@@ -354,7 +371,7 @@
           this._reviewersPendingRemove[type].push(account);
         }
       }
-    },
+    }
 
     /**
      * Resets the state of the _reviewersPendingRemove object, and removes
@@ -380,7 +397,7 @@
           this._reviewersPendingRemove[type] = [];
         }
       }
-    },
+    }
 
     /**
      * Removes an account from the change, both on the backend and the client.
@@ -404,7 +421,7 @@
           }
         }
       });
-    },
+    }
 
     _mapReviewer(reviewer) {
       let reviewerId;
@@ -416,7 +433,7 @@
         confirmed = reviewer.group.confirmed;
       }
       return {reviewer: reviewerId, confirmed};
-    },
+    }
 
     send(includeComments, startReview) {
       this.$.reporting.time(SEND_REPLY_TIMING_LABEL);
@@ -479,7 +496,7 @@
         this.disabled = false;
         throw err;
       });
-    },
+    }
 
     _focusOn(section) {
       // Safeguard- always want to focus on something.
@@ -497,7 +514,7 @@
         const ccEntry = this.$.ccs.focusStart;
         ccEntry.async(ccEntry.focus);
       }
-    },
+    }
 
     _chooseFocusTarget() {
       // If we are the owner and the reviewers field is empty, focus on that.
@@ -509,7 +526,7 @@
 
       // Default to BODY.
       return FocusTarget.BODY;
-    },
+    }
 
     _handle400Error(response) {
       // A call to _saveReview could fail with a server error if erroneous
@@ -551,11 +568,11 @@
         this.fire('server-error', {response});
         return null; // Means that the error has been handled.
       });
-    },
+    }
 
     _computeHideDraftList(drafts) {
       return Object.keys(drafts || {}).length == 0;
-    },
+    }
 
     _computeDraftsTitle(drafts) {
       let total = 0;
@@ -567,13 +584,13 @@
       if (total == 0) { return ''; }
       if (total == 1) { return '1 Draft'; }
       if (total > 1) { return total + ' Drafts'; }
-    },
+    }
 
     _computeMessagePlaceholder(canBeStarted) {
       return canBeStarted ?
         'Add a note for your reviewers...' :
         'Say something nice...';
-    },
+    }
 
     _changeUpdated(changeRecord, owner) {
       // Polymer 2: check for undefined
@@ -582,7 +599,7 @@
       }
 
       this._rebuildReviewerArrays(changeRecord.base, owner);
-    },
+    }
 
     _rebuildReviewerArrays(change, owner) {
       this._owner = owner;
@@ -614,11 +631,11 @@
 
       this._ccs = ccs;
       this._reviewers = reviewers;
-    },
+    }
 
     _accountOrGroupKey(entry) {
       return entry.id || entry._account_id;
-    },
+    }
 
     /**
      * Generates a function to filter out reviewer/CC entries. When isCCs is
@@ -650,23 +667,23 @@
         }
         return this._reviewers.find(finder) === undefined;
       };
-    },
+    }
 
     _getAccount() {
       return this.$.restAPI.getAccount();
-    },
+    }
 
     _cancelTapHandler(e) {
       e.preventDefault();
       this.cancel();
-    },
+    }
 
     cancel() {
       this.fire('cancel', null, {bubbles: false});
       this.$.textarea.closeDropdown();
       this._purgeReviewersPendingRemove(true);
       this._rebuildReviewerArrays(this.change.reviewers, this._owner);
-    },
+    }
 
     _saveTapHandler(e) {
       e.preventDefault();
@@ -678,12 +695,12 @@
       this.send(this._includeComments, false).then(keepReviewers => {
         this._purgeReviewersPendingRemove(false, keepReviewers);
       });
-    },
+    }
 
     _sendTapHandler(e) {
       e.preventDefault();
       this._submit();
-    },
+    }
 
     _submit() {
       if (!this.$.ccs.submitEntryText()) {
@@ -710,12 +727,12 @@
               detail: {message: `Error submitting review ${err}`},
             }));
           });
-    },
+    }
 
     _saveReview(review, opt_errFn) {
       return this.$.restAPI.saveChangeReview(this.change._number, this.patchNum,
           review, opt_errFn);
-    },
+    }
 
     _reviewerPendingConfirmationUpdated(reviewer) {
       if (reviewer === null) {
@@ -725,7 +742,7 @@
             this._ccPendingConfirmation || this._reviewerPendingConfirmation;
         this.$.reviewerConfirmationOverlay.open();
       }
-    },
+    }
 
     _confirmPendingReviewer() {
       if (this._ccPendingConfirmation) {
@@ -735,7 +752,7 @@
         this.$.reviewers.confirmGroup(this._reviewerPendingConfirmation.group);
         this._focusOn(FocusTarget.REVIEWERS);
       }
-    },
+    }
 
     _cancelPendingReviewer() {
       this._ccPendingConfirmation = null;
@@ -744,7 +761,7 @@
       const target =
           this._ccPendingConfirmation ? FocusTarget.CCS : FocusTarget.REVIEWERS;
       this._focusOn(target);
-    },
+    }
 
     _getStorageLocation() {
       // Tests trigger this method without setting change.
@@ -754,12 +771,12 @@
         patchNum: '@change',
         path: '@change',
       };
-    },
+    }
 
     _loadStoredDraft() {
       const draft = this.$.storage.getDraftComment(this._getStorageLocation());
       return draft ? draft.message : '';
-    },
+    }
 
     _handleAccountTextEntry() {
       // When either of the account entries has input added to the autocomplete,
@@ -767,7 +784,7 @@
       //
       // Note: if the text is removed, the save button will not get disabled.
       this._reviewersMutated = true;
-    },
+    }
 
     _draftChanged(newDraft, oldDraft) {
       this.debounce('store', () => {
@@ -780,37 +797,37 @@
               this.draft);
         }
       }, STORAGE_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _handleHeightChanged(e) {
       this.fire('autogrow');
-    },
+    }
 
     _handleLabelsChanged() {
       this._labelsChanged = Object.keys(
           this.$.labelScores.getLabelValues()).length !== 0;
-    },
+    }
 
     _isState(knownLatestState, value) {
       return knownLatestState === value;
-    },
+    }
 
     _reload() {
       // Load the current change without any patch range.
       location.href = this.getBaseUrl() + '/c/' + this.change._number;
-    },
+    }
 
     _computeSendButtonLabel(canBeStarted) {
       return canBeStarted ? ButtonLabels.START_REVIEW : ButtonLabels.SEND;
-    },
+    }
 
     _computeSendButtonTooltip(canBeStarted) {
       return canBeStarted ? ButtonTooltips.START_REVIEW : ButtonTooltips.SEND;
-    },
+    }
 
     _computeSavingLabelClass(savingComments) {
       return savingComments ? 'saving' : '';
-    },
+    }
 
     _computeSendButtonDisabled(buttonLabel, drafts, text, reviewersMutated,
         labelsChanged, includeComments, disabled) {
@@ -831,7 +848,7 @@
       if (buttonLabel === ButtonLabels.START_REVIEW) { return false; }
       const hasDrafts = includeComments && Object.keys(drafts).length;
       return !hasDrafts && !text.length && !reviewersMutated && !labelsChanged;
-    },
+    }
 
     _computePatchSetWarning(patchNum, labelsChanged) {
       let str = `Patch ${patchNum} is not latest.`;
@@ -839,28 +856,30 @@
         str += ' Voting on a non-latest patch will have no effect.';
       }
       return str;
-    },
+    }
 
     setPluginMessage(message) {
       this._pluginMessage = message;
-    },
+    }
 
     _sendDisabledChanged(sendDisabled) {
       this.dispatchEvent(new CustomEvent('send-disabled-changed'));
-    },
+    }
 
     _getReviewerSuggestionsProvider(change) {
       const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
           change._number, Gerrit.SUGGESTIONS_PROVIDERS_USERS_TYPES.REVIEWER);
       provider.init();
       return provider;
-    },
+    }
 
     _getCcSuggestionsProvider(change) {
       const provider = GrReviewerSuggestionsProvider.create(this.$.restAPI,
           change._number, Gerrit.SUGGESTIONS_PROVIDERS_USERS_TYPES.CC);
       provider.init();
       return provider;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrReplyDialog.is, GrReplyDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 76f6f0b..badd62a 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reply-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -1168,7 +1168,7 @@
       MockInteractions.tap(element.$$('gr-button.send'));
       assert.isFalse(sendStub.called);
 
-      element.diffDrafts = {test: true};
+      element.diffDrafts = {test: [{val: true}]};
       flushAsynchronousOperations();
 
       MockInteractions.tap(element.$$('gr-button.send'));
@@ -1180,7 +1180,7 @@
       // computed to false.
       element.diffDrafts = {};
       assert.equal(element.getFocusStops().end, element.$.cancelButton);
-      element.diffDrafts = {test: true};
+      element.diffDrafts = {test: [{val: true}]};
       assert.equal(element.getFocusStops().end, element.$.sendButton);
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
index 8dbdde1..a5875ab1 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.html
@@ -32,51 +32,35 @@
         opacity: .8;
         pointer-events: none;
       }
-      .autocompleteContainer {
-        position: relative;
-      }
-      .hiddenReviewers {
-        margin-top: var(--spacing-s);
-      }
-      .inputContainer {
-        display: flex;
-        margin-top: var(--spacing-xs);
-      }
-      .inputContainer input {
-        flex: 1;
-      }
-      gr-account-chip {
+      .container > :not(:first-child) {
         margin-top: var(--spacing-s);
       }
       gr-button {
         --gr-button: {
-          padding: 5px 0px;
-        }
-      }
-      @media screen and (max-width: 50em), screen and (min-width: 75em) {
-        gr-account-chip:first-of-type {
-          margin-top: 0;
+          padding: 0px 0px;
         }
       }
     </style>
-    <template is="dom-repeat" items="[[_displayedReviewers]]" as="reviewer">
-      <gr-account-chip class="reviewer" account="[[reviewer]]"
-          on-remove="_handleRemove"
-          additional-text="[[_computeReviewerTooltip(reviewer, change)]]"
-          removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]">
-      </gr-account-chip>
-    </template>
-    <gr-button
-        class="hiddenReviewers"
-        link
-        hidden$="[[!_hiddenReviewerCount]]"
-        on-click="_handleViewAll">and [[_hiddenReviewerCount]] more</gr-button>
-    <div class="controlsContainer" hidden$="[[!mutable]]">
+    <div class="container">
+      <template is="dom-repeat" items="[[_displayedReviewers]]" as="reviewer">
+        <gr-account-chip class="reviewer" account="[[reviewer]]"
+            on-remove="_handleRemove"
+            additional-text="[[_computeReviewerTooltip(reviewer, change)]]"
+            removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]">
+        </gr-account-chip>
+      </template>
       <gr-button
+          class="hiddenReviewers"
           link
-          id="addReviewer"
-          class="addReviewer"
-          on-click="_handleAddTap">[[_addLabel]]</gr-button>
+          hidden$="[[!_hiddenReviewerCount]]"
+          on-click="_handleViewAll">and [[_hiddenReviewerCount]] more</gr-button>
+      <div class="controlsContainer" hidden$="[[!mutable]]">
+        <gr-button
+            link
+            id="addReviewer"
+            class="addReviewer"
+            on-click="_handleAddTap">[[_addLabel]]</gr-button>
+      </div>
     </div>
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
index 59c9691..3cc79fa 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list.js
@@ -17,69 +17,75 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-reviewer-list',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrReviewerList extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-reviewer-list'; }
     /**
      * Fired when the "Add reviewer..." button is tapped.
      *
      * @event show-reply-dialog
      */
 
-    properties: {
-      change: Object,
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      mutable: {
-        type: Boolean,
-        value: false,
-      },
-      reviewersOnly: {
-        type: Boolean,
-        value: false,
-      },
-      ccsOnly: {
-        type: Boolean,
-        value: false,
-      },
-      maxReviewersDisplayed: Number,
+    static get properties() {
+      return {
+        change: Object,
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        mutable: {
+          type: Boolean,
+          value: false,
+        },
+        reviewersOnly: {
+          type: Boolean,
+          value: false,
+        },
+        ccsOnly: {
+          type: Boolean,
+          value: false,
+        },
+        maxReviewersDisplayed: Number,
 
-      _displayedReviewers: {
-        type: Array,
-        value() { return []; },
-      },
-      _reviewers: {
-        type: Array,
-        value() { return []; },
-      },
-      _showInput: {
-        type: Boolean,
-        value: false,
-      },
-      _addLabel: {
-        type: String,
-        computed: '_computeAddLabel(ccsOnly)',
-      },
-      _hiddenReviewerCount: {
-        type: Number,
-        computed: '_computeHiddenCount(_reviewers, _displayedReviewers)',
-      },
+        _displayedReviewers: {
+          type: Array,
+          value() { return []; },
+        },
+        _reviewers: {
+          type: Array,
+          value() { return []; },
+        },
+        _showInput: {
+          type: Boolean,
+          value: false,
+        },
+        _addLabel: {
+          type: String,
+          computed: '_computeAddLabel(ccsOnly)',
+        },
+        _hiddenReviewerCount: {
+          type: Number,
+          computed: '_computeHiddenCount(_reviewers, _displayedReviewers)',
+        },
 
-      // Used for testing.
-      _lastAutocompleteRequest: Object,
-      _xhrPromise: Object,
-    },
+        // Used for testing.
+        _lastAutocompleteRequest: Object,
+        _xhrPromise: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_reviewersChanged(change.reviewers.*, change.owner)',
-    ],
+    static get observers() {
+      return [
+        '_reviewersChanged(change.reviewers.*, change.owner)',
+      ];
+    }
 
     /**
      * Converts change.permitted_labels to an array of hashes of label keys to
@@ -100,7 +106,7 @@
         label,
         scores: labels[label].map(v => parseInt(v, 10)),
       }));
-    },
+    }
 
     /**
      * Returns hash of labels to max permitted score.
@@ -114,7 +120,7 @@
                 .map(v => parseInt(v, 10))
                 .reduce((a, b) => Math.max(a, b))}))
           .reduce((acc, i) => Object.assign(acc, i), {});
-    },
+    }
 
     /**
      * Returns max permitted score for reviewer.
@@ -139,7 +145,7 @@
         return 0;
       }
       return NaN;
-    },
+    }
 
     _computeReviewerTooltip(reviewer, change) {
       if (!change || !change.labels) { return ''; }
@@ -160,7 +166,7 @@
       } else {
         return '';
       }
-    },
+    }
 
     _reviewersChanged(changeRecord, owner) {
       // Polymer 2: check for undefined
@@ -185,16 +191,16 @@
         return reviewer._account_id != owner._account_id;
       });
 
-      // If there is one more than the max reviewers, don't show the 'show
-      // more' button, because it takes up just as much space.
+      // If there is one or two more than the max reviewers, don't show the
+      // 'show more' button, because it takes up just as much space.
       if (this.maxReviewersDisplayed &&
-          this._reviewers.length > this.maxReviewersDisplayed + 1) {
+          this._reviewers.length > this.maxReviewersDisplayed + 2) {
         this._displayedReviewers =
           this._reviewers.slice(0, this.maxReviewersDisplayed);
       } else {
         this._displayedReviewers = this._reviewers;
       }
-    },
+    }
 
     _computeHiddenCount(reviewers, displayedReviewers) {
       // Polymer 2: check for undefined
@@ -203,7 +209,7 @@
       }
 
       return reviewers.length - displayedReviewers.length;
-    },
+    }
 
     _computeCanRemoveReviewer(reviewer, mutable) {
       if (!mutable) { return false; }
@@ -217,7 +223,7 @@
         }
       }
       return false;
-    },
+    }
 
     _handleRemove(e) {
       e.preventDefault();
@@ -245,7 +251,7 @@
         this.disabled = false;
         throw err;
       });
-    },
+    }
 
     _handleAddTap(e) {
       e.preventDefault();
@@ -257,18 +263,20 @@
         value.ccsOnly = true;
       }
       this.fire('show-reply-dialog', {value});
-    },
+    }
 
     _handleViewAll(e) {
       this._displayedReviewers = this._reviewers;
-    },
+    }
 
     _removeReviewer(id) {
       return this.$.restAPI.removeChangeReviewer(this.change._number, id);
-    },
+    }
 
     _computeAddLabel(ccsOnly) {
       return ccsOnly ? 'Add CC' : 'Add reviewer';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrReviewerList.is, GrReviewerList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
index ac59235..18f7bc5 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reviewer-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -214,10 +214,10 @@
       assert.isTrue(element.$$('.hiddenReviewers').hidden);
     });
 
-    test('show all reviewers button with 7 reviewers', () => {
+    test('show all reviewers button with 8 reviewers', () => {
       const reviewers = [];
       element.maxReviewersDisplayed = 5;
-      for (let i = 0; i < 7; i++) {
+      for (let i = 0; i < 8; i++) {
         reviewers.push(
             {email: i+'reviewer@google.com', name: 'reviewer-' + i});
       }
@@ -231,9 +231,9 @@
           CC: reviewers,
         },
       };
-      assert.equal(element._hiddenReviewerCount, 2);
+      assert.equal(element._hiddenReviewerCount, 3);
       assert.equal(element._displayedReviewers.length, 5);
-      assert.equal(element._reviewers.length, 7);
+      assert.equal(element._reviewers.length, 8);
       assert.isFalse(element.$$('.hiddenReviewers').hidden);
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
index 518a013..3a6b2df 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
@@ -22,39 +22,42 @@
    *
    * @event thread-list-modified
    */
+  class GrThreadList extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-thread-list'; }
 
-  Polymer({
-    is: 'gr-thread-list',
-
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      change: Object,
-      threads: Array,
-      changeNum: String,
-      loggedIn: Boolean,
-      _sortedThreads: {
-        type: Array,
-      },
-      _filteredThreads: {
-        type: Array,
-        computed: '_computeFilteredThreads(_sortedThreads, _unresolvedOnly, ' +
-            '_draftsOnly)',
-      },
-      _unresolvedOnly: {
-        type: Boolean,
-        value: false,
-      },
-      _draftsOnly: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        change: Object,
+        threads: Array,
+        changeNum: String,
+        loggedIn: Boolean,
+        _sortedThreads: {
+          type: Array,
+        },
+        _filteredThreads: {
+          type: Array,
+          computed: '_computeFilteredThreads(_sortedThreads, ' +
+            '_unresolvedOnly, _draftsOnly)',
+        },
+        _unresolvedOnly: {
+          type: Boolean,
+          value: false,
+        },
+        _draftsOnly: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    observers: ['_computeSortedThreads(threads.*)'],
+    static get observers() { return ['_computeSortedThreads(threads.*)']; }
 
     _computeShowDraftToggle(loggedIn) {
       return loggedIn ? 'show' : '';
-    },
+    }
 
     /**
      * Order as follows:
@@ -68,7 +71,7 @@
       const threads = changeRecord.base;
       if (!threads) { return []; }
       this._updateSortedThreads(threads);
-    },
+    }
 
     _updateSortedThreads(threads) {
       this._sortedThreads =
@@ -90,7 +93,7 @@
             }
             return dateCompare ? dateCompare : c1.id.localeCompare(c2.id);
           });
-    },
+    }
 
     _computeFilteredThreads(sortedThreads, unresolvedOnly, draftsOnly) {
       // Polymer 2: check for undefined
@@ -125,7 +128,7 @@
           return c;
         }
       }).map(threadInfo => threadInfo.thread);
-    },
+    }
 
     _getThreadWithSortInfo(thread) {
       const lastComment = thread.comments[thread.comments.length - 1] || {};
@@ -143,7 +146,7 @@
         hasDraft: !!lastComment.__draft,
         updated: lastComment.updated,
       };
-    },
+    }
 
     removeThread(rootId) {
       for (let i = 0; i < this.threads.length; i++) {
@@ -154,11 +157,11 @@
           return;
         }
       }
-    },
+    }
 
     _handleThreadDiscard(e) {
       this.removeThread(e.detail.rootId);
-    },
+    }
 
     _handleCommentsChanged(e) {
       // Reset threads so thread computations occur on deep array changes to
@@ -167,10 +170,12 @@
 
       this.dispatchEvent(new CustomEvent('thread-list-modified',
           {detail: {rootId: e.detail.rootId, path: e.detail.path}}));
-    },
+    }
 
     _isOnParent(side) {
       return !!side;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrThreadList.is, GrThreadList);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
index e736651..b29246d 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-thread-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
index 092204a..a3ae1f9 100644
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.js
@@ -27,41 +27,46 @@
     'pull',
   ];
 
-  Polymer({
-    is: 'gr-upload-help-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrUploadHelpDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-upload-help-dialog'; }
     /**
      * Fired when the user presses the close button.
      *
      * @event close
      */
 
-    properties: {
-      revision: Object,
-      targetBranch: String,
-      _commitCommand: {
-        type: String,
-        value: COMMIT_COMMAND,
-        readOnly: true,
-      },
-      _fetchCommand: {
-        type: String,
-        computed: '_computeFetchCommand(revision, ' +
+    static get properties() {
+      return {
+        revision: Object,
+        targetBranch: String,
+        _commitCommand: {
+          type: String,
+          value: COMMIT_COMMAND,
+          readOnly: true,
+        },
+        _fetchCommand: {
+          type: String,
+          computed: '_computeFetchCommand(revision, ' +
             '_preferredDownloadCommand, _preferredDownloadScheme)',
-      },
-      _preferredDownloadCommand: String,
-      _preferredDownloadScheme: String,
-      _pushCommand: {
-        type: String,
-        computed: '_computePushCommand(targetBranch)',
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+        },
+        _preferredDownloadCommand: String,
+        _preferredDownloadScheme: String,
+        _pushCommand: {
+          type: String,
+          computed: '_computePushCommand(targetBranch)',
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this.$.restAPI.getLoggedIn().then(loggedIn => {
         if (loggedIn) {
           return this.$.restAPI.getPreferences();
@@ -72,13 +77,13 @@
           this._preferredDownloadScheme = prefs.download_scheme;
         }
       });
-    },
+    }
 
     _handleCloseTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('close', null, {bubbles: false});
-    },
+    }
 
     _computeFetchCommand(revision, preferredDownloadCommand,
         preferredDownloadScheme) {
@@ -126,10 +131,12 @@
       }
 
       return undefined;
-    },
+    }
 
     _computePushCommand(targetBranch) {
       return PUSH_COMMAND_PREFIX + targetBranch;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrUploadHelpDialog.is, GrUploadHelpDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html
index 577b978..76377fb 100644
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-upload-help-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
index 3c2096c..5152ef9 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
@@ -21,6 +21,7 @@
 <link rel="import" href="../../shared/gr-dropdown/gr-dropdown.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../../shared/gr-avatar/gr-avatar.html">
 
 <dom-module id="gr-account-dropdown">
   <template>
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
index 7cbe988..4f51a02 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
@@ -19,29 +19,39 @@
 
   const INTERPOLATE_URL_PATTERN = /\$\{([\w]+)\}/g;
 
-  Polymer({
-    is: 'gr-account-dropdown',
+  /**
+    * @appliesMixin Gerrit.DisplayNameMixin
+    */
+  class GrAccountDropdown extends Polymer.mixinBehaviors( [
+    Gerrit.DisplayNameBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-dropdown'; }
 
-    properties: {
-      account: Object,
-      config: Object,
-      links: {
-        type: Array,
-        computed: '_getLinks(_switchAccountUrl, _path)',
-      },
-      topContent: {
-        type: Array,
-        computed: '_getTopContent(account)',
-      },
-      _path: {
-        type: String,
-        value: '/',
-      },
-      _hasAvatars: Boolean,
-      _switchAccountUrl: String,
-    },
+    static get properties() {
+      return {
+        account: Object,
+        config: Object,
+        links: {
+          type: Array,
+          computed: '_getLinks(_switchAccountUrl, _path)',
+        },
+        topContent: {
+          type: Array,
+          computed: '_getTopContent(account)',
+        },
+        _path: {
+          type: String,
+          value: '/',
+        },
+        _hasAvatars: Boolean,
+        _switchAccountUrl: String,
+      };
+    }
 
     attached() {
+      super.attached();
       this._handleLocationChange();
       this.listen(window, 'location-change', '_handleLocationChange');
       this.$.restAPI.getConfig().then(cfg => {
@@ -54,15 +64,12 @@
         }
         this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
       });
-    },
-
-    behaviors: [
-      Gerrit.DisplayNameBehavior,
-    ],
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'location-change', '_handleLocationChange');
-    },
+    }
 
     _getLinks(switchAccountUrl, path) {
       // Polymer 2: check for undefined
@@ -78,30 +85,32 @@
       }
       links.push({name: 'Sign out', url: '/logout'});
       return links;
-    },
+    }
 
     _getTopContent(account) {
       return [
         {text: this._accountName(account), bold: true},
         {text: account.email ? account.email : ''},
       ];
-    },
+    }
 
     _handleLocationChange() {
       this._path =
           window.location.pathname +
           window.location.search +
           window.location.hash;
-    },
+    }
 
     _interpolateUrl(url, replacements) {
       return url.replace(INTERPOLATE_URL_PATTERN, (match, p1) => {
         return replacements[p1] || '';
       });
-    },
+    }
 
     _accountName(account) {
       return this.getUserName(this.config, account, true);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountDropdown.is, GrAccountDropdown);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html
index e29faa8..9dafb74 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-dropdown</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.js b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.js
index 8d3b58e..2655140 100644
--- a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.js
+++ b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.js
@@ -17,21 +17,26 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-error-dialog',
-
+  class GrErrorDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-error-dialog'; }
     /**
      * Fired when the dismiss button is pressed.
      *
      * @event dismiss
      */
 
-    properties: {
-      text: String,
-    },
+    static get properties() {
+      return {
+        text: String,
+      };
+    }
 
     _handleConfirm() {
       this.dispatchEvent(new CustomEvent('dismiss'));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrErrorDialog.is, GrErrorDialog);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html
index 648f8be..dd4a71a 100644
--- a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-error-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index 5865e3c..7437187 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -25,40 +25,47 @@
   const TOO_MANY_FILES = 'too many files to find conflicts';
   const AUTHENTICATION_REQUIRED = 'Authentication required\n';
 
-  Polymer({
-    is: 'gr-error-manager',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrErrorManager extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-error-manager'; }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-    ],
-
-    properties: {
+    static get properties() {
+      return {
       /**
        * The ID of the account that was logged in when the app was launched. If
        * not set, then there was no account at launch.
        */
-      knownAccountId: Number,
+        knownAccountId: Number,
 
-      /** @type {?Object} */
-      _alertElement: Object,
-      /** @type {?number} */
-      _hideAlertHandle: Number,
-      _refreshingCredentials: {
-        type: Boolean,
-        value: false,
-      },
+        /** @type {?Object} */
+        _alertElement: Object,
+        /** @type {?number} */
+        _hideAlertHandle: Number,
+        _refreshingCredentials: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * The time (in milliseconds) since the most recent credential check.
        */
-      _lastCredentialCheck: {
-        type: Number,
-        value() { return Date.now(); },
-      },
-    },
+        _lastCredentialCheck: {
+          type: Number,
+          value() { return Date.now(); },
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this.listen(document, 'server-error', '_handleServerError');
       this.listen(document, 'network-error', '_handleNetworkError');
       this.listen(document, 'auth-error', '_handleAuthError');
@@ -66,9 +73,10 @@
       this.listen(document, 'show-error', '_handleShowErrorDialog');
       this.listen(document, 'visibilitychange', '_handleVisibilityChange');
       this.listen(document, 'show-auth-required', '_handleAuthRequired');
-    },
+    }
 
     detached() {
+      super.detached();
       this._clearHideAlertHandle();
       this.unlisten(document, 'server-error', '_handleServerError');
       this.unlisten(document, 'network-error', '_handleNetworkError');
@@ -76,20 +84,20 @@
       this.unlisten(document, 'show-auth-required', '_handleAuthRequired');
       this.unlisten(document, 'visibilitychange', '_handleVisibilityChange');
       this.unlisten(document, 'show-error', '_handleShowErrorDialog');
-    },
+    }
 
     _shouldSuppressError(msg) {
       return msg.includes(TOO_MANY_FILES);
-    },
+    }
 
     _handleAuthRequired() {
       this._showAuthErrorAlert(
           'Log in is required to perform that action.', 'Log in.');
-    },
+    }
 
     _handleAuthError() {
       this._showAuthErrorAlert('Auth error', 'Refresh credentials.');
-    },
+    }
 
     _handleServerError(e) {
       const {request, response} = e.detail;
@@ -113,7 +121,7 @@
             }
             console.error(errorText);
           });
-    },
+    }
 
     _constructServerErrorMsg({errorText, status, statusText, url}) {
       let err = `Error ${status}`;
@@ -122,21 +130,21 @@
       if (errorText) { err += errorText; }
       if (url) { err += `\nEndpoint: ${url}`; }
       return err;
-    },
+    }
 
     _handleShowAlert(e) {
       this._showAlert(e.detail.message, e.detail.action, e.detail.callback,
           e.detail.dismissOnNavigation);
-    },
+    }
 
     _handleNetworkError(e) {
       this._showAlert('Server unavailable');
       console.error(e.detail.error.message);
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     /**
      * @param {string} text
@@ -161,7 +169,7 @@
       const el = this._createToastAlert();
       el.show(text, opt_actionText, opt_actionCallback);
       this._alertElement = el;
-    },
+    }
 
     _hideAlert() {
       if (!this._alertElement) { return; }
@@ -171,14 +179,14 @@
 
       // Remove listener for page navigation, if it exists.
       this.unlisten(document, 'location-change', '_hideAlert');
-    },
+    }
 
     _clearHideAlertHandle() {
       if (this._hideAlertHandle != null) {
         this.cancelAsync(this._hideAlertHandle);
         this._hideAlertHandle = null;
       }
-    },
+    }
 
     _showAuthErrorAlert(errorText, actionText) {
       // TODO(viktard): close alert if it's not for auth error.
@@ -193,13 +201,13 @@
       if (!document.hidden) {
         this._handleVisibilityChange();
       }
-    },
+    }
 
     _createToastAlert() {
       const el = document.createElement('gr-alert');
       el.toast = true;
       return el;
-    },
+    }
 
     _handleVisibilityChange() {
       // Ignore when the page is transitioning to hidden (or hidden is
@@ -216,12 +224,12 @@
         this._lastCredentialCheck = Date.now();
         this.$.restAPI.checkCredentials();
       }
-    },
+    }
 
     _requestCheckLoggedIn() {
       this.debounce(
           'checkLoggedIn', this._checkSignedIn, CHECK_SIGN_IN_INTERVAL_MS);
-    },
+    }
 
     _checkSignedIn() {
       this.$.restAPI.checkCredentials().then(account => {
@@ -242,11 +250,11 @@
           }
         }
       });
-    },
+    }
 
     _reloadPage() {
       window.location.reload();
-    },
+    }
 
     _createLoginPopup() {
       const left = window.screenLeft +
@@ -262,31 +270,33 @@
       window.open(this.getBaseUrl() +
           '/login/%3FcloseAfterLogin', '_blank', options.join(','));
       this.listen(window, 'focus', '_handleWindowFocus');
-    },
+    }
 
     _handleCredentialRefreshed() {
       this.unlisten(window, 'focus', '_handleWindowFocus');
       this._refreshingCredentials = false;
       this._hideAlert();
       this._showAlert('Credentials refreshed.');
-    },
+    }
 
     _handleWindowFocus() {
       this.flushDebouncer('checkLoggedIn');
-    },
+    }
 
     _handleShowErrorDialog(e) {
       this._showErrorDialog(e.detail.message);
-    },
+    }
 
     _handleDismissErrorDialog() {
       this.$.errorOverlay.close();
-    },
+    }
 
     _showErrorDialog(message) {
       this.$.reporting.reportErrorDialog(message);
       this.$.errorDialog.text = message;
       this.$.errorOverlay.open();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrErrorManager.is, GrErrorManager);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
index 9140c17..84b6717 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-error-manager</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
index 89d1091..2b86170 100644
--- a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
+++ b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display.js
@@ -17,20 +17,26 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-key-binding-display',
+  class GrKeyBindingDisplay extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-key-binding-display'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {Array<string>} */
-      binding: Array,
-    },
+        binding: Array,
+      };
+    }
 
     _computeModifiers(binding) {
       return binding.slice(0, binding.length - 1);
-    },
+    }
 
     _computeKey(binding) {
       return binding[binding.length - 1];
-    },
-  });
+    }
+  }
+
+  customElements.define(GrKeyBindingDisplay.is, GrKeyBindingDisplay);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html
index 39c8af8..e0d2d40 100644
--- a/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html
+++ b/polygerrit-ui/app/elements/core/gr-key-binding-display/gr-key-binding-display_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-key-binding-display</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
index 4bc6e11..e16c975 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.js
@@ -19,60 +19,68 @@
 
   const {ShortcutSection} = window.Gerrit.KeyboardShortcutBinder;
 
-  Polymer({
-    is: 'gr-keyboard-shortcuts-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrKeyboardShortcutsDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-keyboard-shortcuts-dialog'; }
     /**
      * Fired when the user presses the close button.
      *
      * @event close
      */
 
-    properties: {
-      _left: Array,
-      _right: Array,
+    static get properties() {
+      return {
+        _left: Array,
+        _right: Array,
 
-      _propertyBySection: {
-        type: Object,
-        value() {
-          return {
-            [ShortcutSection.EVERYWHERE]: '_everywhere',
-            [ShortcutSection.NAVIGATION]: '_navigation',
-            [ShortcutSection.DASHBOARD]: '_dashboard',
-            [ShortcutSection.CHANGE_LIST]: '_changeList',
-            [ShortcutSection.ACTIONS]: '_actions',
-            [ShortcutSection.REPLY_DIALOG]: '_replyDialog',
-            [ShortcutSection.FILE_LIST]: '_fileList',
-            [ShortcutSection.DIFFS]: '_diffs',
-          };
+        _propertyBySection: {
+          type: Object,
+          value() {
+            return {
+              [ShortcutSection.EVERYWHERE]: '_everywhere',
+              [ShortcutSection.NAVIGATION]: '_navigation',
+              [ShortcutSection.DASHBOARD]: '_dashboard',
+              [ShortcutSection.CHANGE_LIST]: '_changeList',
+              [ShortcutSection.ACTIONS]: '_actions',
+              [ShortcutSection.REPLY_DIALOG]: '_replyDialog',
+              [ShortcutSection.FILE_LIST]: '_fileList',
+              [ShortcutSection.DIFFS]: '_diffs',
+            };
+          },
         },
-      },
-    },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    hostAttributes: {
-      role: 'dialog',
-    },
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'dialog');
+    }
 
     attached() {
+      super.attached();
       this.addKeyboardShortcutDirectoryListener(
           this._onDirectoryUpdated.bind(this));
-    },
+    }
 
     detached() {
+      super.detached();
       this.removeKeyboardShortcutDirectoryListener(
           this._onDirectoryUpdated.bind(this));
-    },
+    }
 
     _handleCloseTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('close', null, {bubbles: false});
-    },
+    }
 
     _onDirectoryUpdated(directory) {
       const left = [];
@@ -122,6 +130,9 @@
 
       this.set('_left', left);
       this.set('_right', right);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrKeyboardShortcutsDialog.is,
+      GrKeyboardShortcutsDialog);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html
index 1a3d6c7..b713aa1 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-key-binding-display</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
index 773ad68..1ae1e93 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.js
@@ -69,94 +69,107 @@
     'CUSTOM_EXTENSION',
   ]);
 
-  Polymer({
-    is: 'gr-main-header',
+  /**
+    * @appliesMixin Gerrit.AdminNavMixin
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.DocsUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrMainHeader extends Polymer.mixinBehaviors( [
+    Gerrit.AdminNavBehavior,
+    Gerrit.BaseUrlBehavior,
+    Gerrit.DocsUrlBehavior,
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-main-header'; }
 
-    hostAttributes: {
-      role: 'banner',
-    },
-
-    properties: {
-      searchQuery: {
-        type: String,
-        notify: true,
-      },
-      loggedIn: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-      loading: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-
-      /** @type {?Object} */
-      _account: Object,
-      _adminLinks: {
-        type: Array,
-        value() { return []; },
-      },
-      _defaultLinks: {
-        type: Array,
-        value() {
-          return DEFAULT_LINKS;
+    static get properties() {
+      return {
+        searchQuery: {
+          type: String,
+          notify: true,
         },
-      },
-      _docBaseUrl: {
-        type: String,
-        value: null,
-      },
-      _links: {
-        type: Array,
-        computed: '_computeLinks(_defaultLinks, _userLinks, _adminLinks, ' +
+        loggedIn: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+        loading: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+
+        /** @type {?Object} */
+        _account: Object,
+        _adminLinks: {
+          type: Array,
+          value() { return []; },
+        },
+        _defaultLinks: {
+          type: Array,
+          value() {
+            return DEFAULT_LINKS;
+          },
+        },
+        _docBaseUrl: {
+          type: String,
+          value: null,
+        },
+        _links: {
+          type: Array,
+          computed: '_computeLinks(_defaultLinks, _userLinks, _adminLinks, ' +
             '_topMenus, _docBaseUrl)',
-      },
-      _loginURL: {
-        type: String,
-        value: '/login',
-      },
-      _userLinks: {
-        type: Array,
-        value() { return []; },
-      },
-      _topMenus: {
-        type: Array,
-        value() { return []; },
-      },
-      _registerText: {
-        type: String,
-        value: 'Sign up',
-      },
-      _registerURL: {
-        type: String,
-        value: null,
-      },
-    },
+        },
+        _loginURL: {
+          type: String,
+          value: '/login',
+        },
+        _userLinks: {
+          type: Array,
+          value() { return []; },
+        },
+        _topMenus: {
+          type: Array,
+          value() { return []; },
+        },
+        _registerText: {
+          type: String,
+          value: 'Sign up',
+        },
+        _registerURL: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.AdminNavBehavior,
-      Gerrit.BaseUrlBehavior,
-      Gerrit.DocsUrlBehavior,
-      Gerrit.FireBehavior,
-    ],
+    static get observers() {
+      return [
+        '_accountLoaded(_account)',
+      ];
+    }
 
-    observers: [
-      '_accountLoaded(_account)',
-    ],
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'banner');
+    }
 
     attached() {
+      super.attached();
       this._loadAccount();
       this._loadConfig();
       this.listen(window, 'location-change', '_handleLocationChange');
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'location-change', '_handleLocationChange');
-    },
+    }
 
     reload() {
       this._loadAccount();
-    },
+    }
 
     _handleLocationChange(e) {
       const baseUrl = this.getBaseUrl();
@@ -173,11 +186,11 @@
             window.location.search +
             window.location.hash);
       }
-    },
+    }
 
     _computeRelativeURL(path) {
       return '//' + window.location.host + this.getBaseUrl() + path;
-    },
+    }
 
     _computeLinks(defaultLinks, userLinks, adminLinks, topMenus, docBaseUrl) {
       // Polymer 2: check for undefined
@@ -232,7 +245,7 @@
         }
       }
       return links;
-    },
+    }
 
     _getDocLinks(docBaseUrl, docLinks) {
       if (!docBaseUrl || !docLinks) {
@@ -249,7 +262,7 @@
           target: '_blank',
         };
       });
-    },
+    }
 
     _loadAccount() {
       this.loading = true;
@@ -273,7 +286,7 @@
               this._adminLinks = res.links;
             });
       });
-    },
+    }
 
     _loadConfig() {
       this.$.restAPI.getConfig()
@@ -282,7 +295,7 @@
             return this.getDocsBaseUrl(config, this.$.restAPI);
           })
           .then(docBaseUrl => { this._docBaseUrl = docBaseUrl; });
-    },
+    }
 
     _accountLoaded(account) {
       if (!account) { return; }
@@ -290,7 +303,7 @@
       this.$.restAPI.getPreferences().then(prefs => {
         this._userLinks = prefs.my.map(this._fixCustomMenuItem);
       });
-    },
+    }
 
     _retrieveRegisterURL(config) {
       if (AUTH_TYPES_WITH_REGISTER_URL.has(config.auth.auth_type)) {
@@ -299,11 +312,11 @@
           this._registerText = config.auth.register_text;
         }
       }
-    },
+    }
 
     _computeIsInvisible(registerURL) {
       return registerURL ? '' : 'invisible';
-    },
+    }
 
     _fixCustomMenuItem(linkObj) {
       // Normalize all urls to PolyGerrit style.
@@ -321,17 +334,17 @@
       delete linkObj.target;
 
       return linkObj;
-    },
+    }
 
     _generateSettingsLink() {
       return this.getBaseUrl() + '/settings/';
-    },
+    }
 
     _onMobileSearchTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('mobile-search', null, {bubbles: false});
-    },
+    }
 
     _computeLinkGroupClass(linkGroup) {
       if (linkGroup && linkGroup.class) {
@@ -339,6 +352,8 @@
       }
 
       return '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrMainHeader.is, GrMainHeader);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
index ea0056f..46e7d32 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-main-header</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html
index 73ce86a..ca44430 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-navigation</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
index 4c477cb..d169728 100644
--- a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
@@ -143,18 +143,22 @@
   catchErrors();
 
   // PerformanceObserver interface is a browser API.
-  if (PerformanceObserver) {
-    const catchLongJsTasks = new PerformanceObserver(list => {
-      for (const task of list.getEntries()) {
-        // We are interested in longtask longer than 200 ms (default is 50 ms)
-        if (task.duration > 200) {
-          GrReporting.prototype.reporter(TIMING.TYPE,
-              TIMING.CATEGORY_UI_LATENCY, `Task ${task.name}`,
-              Math.round(task.duration), false);
+  if (window.PerformanceObserver) {
+    const supportedEntryTypes = PerformanceObserver.supportedEntryTypes || [];
+    // Safari doesn't support longtask yet
+    if (supportedEntryTypes.includes('longtask')) {
+      const catchLongJsTasks = new PerformanceObserver(list => {
+        for (const task of list.getEntries()) {
+          // We are interested in longtask longer than 200 ms (default is 50 ms)
+          if (task.duration > 200) {
+            GrReporting.prototype.reporter(TIMING.TYPE,
+                TIMING.CATEGORY_UI_LATENCY, `Task ${task.name}`,
+                Math.round(task.duration), false);
+          }
         }
-      }
-    });
-    catchLongJsTasks.observe({entryTypes: ['longtask']});
+      });
+      catchLongJsTasks.observe({entryTypes: ['longtask']});
+    }
   }
 
   // The Polymer pass of JSCompiler requires this to be reassignable
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
index 736fa54..c2c0297 100644
--- a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reporting</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index 7e47912..a3bf6c9 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -207,38 +207,46 @@
     });
   })();
 
-  Polymer({
-    is: 'gr-router',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrRouter extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-router'; }
 
-    properties: {
-      _app: {
-        type: Object,
-        value: app,
-      },
-      _isRedirecting: Boolean,
-      // This variable is to differentiate between internal navigation (false)
-      // and for first navigation in app after loaded from server (true).
-      _isInitialLoad: {
-        type: Boolean,
-        value: true,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    static get properties() {
+      return {
+        _app: {
+          type: Object,
+          value: app,
+        },
+        _isRedirecting: Boolean,
+        // This variable is to differentiate between internal navigation (false)
+        // and for first navigation in app after loaded from server (true).
+        _isInitialLoad: {
+          type: Boolean,
+          value: true,
+        },
+      };
+    }
 
     start() {
       if (!this._app) { return; }
       this._startRouter();
-    },
+    }
 
     _setParams(params) {
       this._appElement().params = params;
-    },
+    }
 
     _appElement() {
       // In Polymer2 you have to reach through the shadow root of the app
@@ -248,12 +256,12 @@
       return document.getElementById('app-element') ||
           document.getElementById('app').shadowRoot.getElementById(
               'app-element');
-    },
+    }
 
     _redirect(url) {
       this._isRedirecting = true;
       page.redirect(url);
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -285,7 +293,7 @@
       }
 
       return base + url;
-    },
+    }
 
     _generateWeblinks(params) {
       const type = params.type;
@@ -299,7 +307,7 @@
         default:
           console.warn(`Unsupported weblink ${type}!`);
       }
-    },
+    }
 
     _getPatchSetWeblink(params) {
       const {commit, options} = params;
@@ -311,7 +319,7 @@
       } else {
         return {name, url: weblink.url};
       }
-    },
+    }
 
     _firstCodeBrowserWeblink(weblinks) {
       // This is an ordered whitelist of web link types that provide direct
@@ -323,7 +331,7 @@
         if (weblink) { return weblink; }
       }
       return null;
-    },
+    }
 
     _getBrowseCommitWeblink(weblinks, config) {
       if (!weblinks) { return null; }
@@ -339,7 +347,7 @@
       }
       if (!weblink) { return null; }
       return weblink;
-    },
+    }
 
     _getChangeWeblinks({repo, commit, options: {weblinks, config}}) {
       if (!weblinks || !weblinks.length) return [];
@@ -348,11 +356,11 @@
         !commitWeblink ||
         !commitWeblink.name ||
         weblink.name !== commitWeblink.name);
-    },
+    }
 
     _getFileWebLinks({repo, commit, file, options: {weblinks}}) {
       return weblinks;
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -399,7 +407,7 @@
       }
 
       return '/q/' + operators.join('+') + offsetExpr;
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -423,7 +431,7 @@
       } else {
         return `/c/${params.changeNum}${suffix}`;
       }
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -448,7 +456,7 @@
         // User dashboard.
         return `/dashboard/${params.user || 'self'}`;
       }
-    },
+    }
 
     /**
      * @param {!Array<!{name: string, query: string}>} sections
@@ -465,7 +473,7 @@
         return encodeURIComponent(section.name) + '=' +
             encodeURIComponent(query);
       });
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -491,7 +499,7 @@
       } else {
         return `/c/${params.changeNum}${suffix}`;
       }
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -505,7 +513,7 @@
         url += ',audit-log';
       }
       return url;
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -525,7 +533,7 @@
         url += ',dashboards';
       }
       return url;
-    },
+    }
 
     /**
      * @param {!Object} params
@@ -533,7 +541,7 @@
      */
     _generateSettingsUrl(params) {
       return '/settings';
-    },
+    }
 
     /**
      * Given an object of parameters, potentially including a `patchNum` or a
@@ -547,7 +555,7 @@
       if (params.patchNum) { range = '' + params.patchNum; }
       if (params.basePatchNum) { range = params.basePatchNum + '..' + range; }
       return range;
-    },
+    }
 
     /**
      * Given a set of params without a project, gets the project from the rest
@@ -571,7 +579,7 @@
             this._normalizePatchRangeParams(params);
             this._redirect(this._generateUrl(params));
           });
-    },
+    }
 
     /**
      * Normalizes the params object, and determines if the URL needs to be
@@ -600,7 +608,7 @@
         params.basePatchNum = null;
       }
       return needsRedirect;
-    },
+    }
 
     /**
      * Redirect the user to login using the given return-URL for redirection
@@ -611,7 +619,7 @@
       const basePath = this.getBaseUrl() || '';
       page(
           '/login/' + encodeURIComponent(returnUrl.substring(basePath.length)));
-    },
+    }
 
     /**
      * Hashes parsed by page.js exclude "inner" hashes, so a URL like "/a#b#c"
@@ -622,7 +630,7 @@
      */
     _getHashFromCanonicalPath(canonicalPath) {
       return canonicalPath.split('#').slice(1).join('#');
-    },
+    }
 
     _parseLineAddress(hash) {
       const match = hash.match(LINE_ADDRESS_PATTERN);
@@ -631,7 +639,7 @@
         leftSide: !!match[1],
         lineNum: parseInt(match[2], 10),
       };
-    },
+    }
 
     /**
      * Check to see if the user is logged in and return a promise that only
@@ -650,12 +658,12 @@
           return Promise.reject(new Error());
         }
       });
-    },
+    }
 
     /**  Page.js middleware that warms the REST API's logged-in cache line. */
     _loadUserMiddleware(ctx, next) {
       this.$.restAPI.getLoggedIn().then(() => { next(); });
-    },
+    }
 
     /**
      * Map a route to a method on the router.
@@ -682,7 +690,7 @@
           this._redirectIfNotLoggedIn(data) : Promise.resolve();
         promise.then(() => { this[handlerName](data); });
       });
-    },
+    }
 
     _startRouter() {
       const base = this.getBaseUrl();
@@ -878,7 +886,7 @@
       this._mapRoute(RoutePattern.DEFAULT, '_handleDefaultRoute');
 
       page.start();
-    },
+    }
 
     /**
      * @param {!Object} data
@@ -919,7 +927,7 @@
           this._redirect('/q/status:open');
         }
       });
-    },
+    }
 
     /**
      * Decode an application/x-www-form-urlencoded string.
@@ -929,7 +937,7 @@
      */
     _decodeQueryString(qs) {
       return decodeURIComponent(qs.replace(PLUS_PATTERN, ' '));
-    },
+    }
 
     /**
      * Parse a query string (e.g. window.location.search) into an array of
@@ -961,7 +969,7 @@
         }
       });
       return params;
-    },
+    }
 
     /**
      * Handle dashboard routes. These may be user, or project dashboards.
@@ -986,7 +994,7 @@
           });
         }
       });
-    },
+    }
 
     /**
      * Handle custom dashboard routes.
@@ -1038,7 +1046,7 @@
       // Redirect /dashboard/ -> /dashboard/self.
       this._redirect('/dashboard/self');
       return Promise.resolve();
-    },
+    }
 
     _handleProjectDashboardRoute(data) {
       const project = data.params[0];
@@ -1048,22 +1056,22 @@
         dashboard: decodeURIComponent(data.params[1]),
       });
       this.$.reporting.setRepoName(project);
-    },
+    }
 
     _handleGroupInfoRoute(data) {
       this._redirect('/admin/groups/' + encodeURIComponent(data.params[0]));
-    },
+    }
 
     _handleGroupSelfRedirectRoute(data) {
       this._redirect('/settings/#Groups');
-    },
+    }
 
     _handleGroupRoute(data) {
       this._setParams({
         view: Gerrit.Nav.View.GROUP,
         groupId: data.params[0],
       });
-    },
+    }
 
     _handleGroupAuditLogRoute(data) {
       this._setParams({
@@ -1071,7 +1079,7 @@
         detail: Gerrit.Nav.GroupDetailView.LOG,
         groupId: data.params[0],
       });
-    },
+    }
 
     _handleGroupMembersRoute(data) {
       this._setParams({
@@ -1079,7 +1087,7 @@
         detail: Gerrit.Nav.GroupDetailView.MEMBERS,
         groupId: data.params[0],
       });
-    },
+    }
 
     _handleGroupListOffsetRoute(data) {
       this._setParams({
@@ -1089,7 +1097,7 @@
         filter: null,
         openCreateModal: data.hash === 'create',
       });
-    },
+    }
 
     _handleGroupListFilterOffsetRoute(data) {
       this._setParams({
@@ -1098,7 +1106,7 @@
         offset: data.params.offset,
         filter: data.params.filter,
       });
-    },
+    }
 
     _handleGroupListFilterRoute(data) {
       this._setParams({
@@ -1106,7 +1114,7 @@
         adminView: 'gr-admin-group-list',
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handleProjectsOldRoute(data) {
       let params = '';
@@ -1119,7 +1127,7 @@
       }
 
       this._redirect(`/admin/repos/${params}`);
-    },
+    }
 
     _handleRepoCommandsRoute(data) {
       const repo = data.params[0];
@@ -1129,7 +1137,7 @@
         repo,
       });
       this.$.reporting.setRepoName(repo);
-    },
+    }
 
     _handleRepoAccessRoute(data) {
       const repo = data.params[0];
@@ -1139,7 +1147,7 @@
         repo,
       });
       this.$.reporting.setRepoName(repo);
-    },
+    }
 
     _handleRepoDashboardsRoute(data) {
       const repo = data.params[0];
@@ -1149,7 +1157,7 @@
         repo,
       });
       this.$.reporting.setRepoName(repo);
-    },
+    }
 
     _handleBranchListOffsetRoute(data) {
       this._setParams({
@@ -1159,7 +1167,7 @@
         offset: data.params[2] || 0,
         filter: null,
       });
-    },
+    }
 
     _handleBranchListFilterOffsetRoute(data) {
       this._setParams({
@@ -1169,7 +1177,7 @@
         offset: data.params.offset,
         filter: data.params.filter,
       });
-    },
+    }
 
     _handleBranchListFilterRoute(data) {
       this._setParams({
@@ -1178,7 +1186,7 @@
         repo: data.params.repo,
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handleTagListOffsetRoute(data) {
       this._setParams({
@@ -1188,7 +1196,7 @@
         offset: data.params[2] || 0,
         filter: null,
       });
-    },
+    }
 
     _handleTagListFilterOffsetRoute(data) {
       this._setParams({
@@ -1198,7 +1206,7 @@
         offset: data.params.offset,
         filter: data.params.filter,
       });
-    },
+    }
 
     _handleTagListFilterRoute(data) {
       this._setParams({
@@ -1207,7 +1215,7 @@
         repo: data.params.repo,
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handleRepoListOffsetRoute(data) {
       this._setParams({
@@ -1217,7 +1225,7 @@
         filter: null,
         openCreateModal: data.hash === 'create',
       });
-    },
+    }
 
     _handleRepoListFilterOffsetRoute(data) {
       this._setParams({
@@ -1226,7 +1234,7 @@
         offset: data.params.offset,
         filter: data.params.filter,
       });
-    },
+    }
 
     _handleRepoListFilterRoute(data) {
       this._setParams({
@@ -1234,19 +1242,19 @@
         adminView: 'gr-repo-list',
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handleCreateProjectRoute(data) {
       // Redirects the legacy route to the new route, which displays the project
       // list with a hash 'create'.
       this._redirect('/admin/repos#create');
-    },
+    }
 
     _handleCreateGroupRoute(data) {
       // Redirects the legacy route to the new route, which displays the group
       // list with a hash 'create'.
       this._redirect('/admin/groups#create');
-    },
+    }
 
     _handleRepoRoute(data) {
       const repo = data.params[0];
@@ -1255,7 +1263,7 @@
         repo,
       });
       this.$.reporting.setRepoName(repo);
-    },
+    }
 
     _handlePluginListOffsetRoute(data) {
       this._setParams({
@@ -1264,7 +1272,7 @@
         offset: data.params[1] || 0,
         filter: null,
       });
-    },
+    }
 
     _handlePluginListFilterOffsetRoute(data) {
       this._setParams({
@@ -1273,7 +1281,7 @@
         offset: data.params.offset,
         filter: data.params.filter,
       });
-    },
+    }
 
     _handlePluginListFilterRoute(data) {
       this._setParams({
@@ -1281,14 +1289,14 @@
         adminView: 'gr-plugin-list',
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handlePluginListRoute(data) {
       this._setParams({
         view: Gerrit.Nav.View.ADMIN,
         adminView: 'gr-plugin-list',
       });
-    },
+    }
 
     _handleQueryRoute(data) {
       this._setParams({
@@ -1296,15 +1304,15 @@
         query: data.params[0],
         offset: data.params[2],
       });
-    },
+    }
 
     _handleQueryLegacySuffixRoute(ctx) {
       this._redirect(ctx.path.replace(LEGACY_QUERY_SUFFIX_PATTERN, ''));
-    },
+    }
 
     _handleChangeNumberLegacyRoute(ctx) {
       this._redirect('/c/' + encodeURIComponent(ctx.params[0]));
-    },
+    }
 
     _handleChangeRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1318,7 +1326,7 @@
 
       this.$.reporting.setRepoName(params.project);
       this._redirectOrNavigate(params);
-    },
+    }
 
     _handleDiffRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1338,7 +1346,7 @@
       }
       this.$.reporting.setRepoName(params.project);
       this._redirectOrNavigate(params);
-    },
+    }
 
     _handleChangeLegacyRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1351,11 +1359,11 @@
       };
 
       this._normalizeLegacyRouteParams(params);
-    },
+    }
 
     _handleLegacyLinenum(ctx) {
       this._redirect(ctx.path.replace(LEGACY_LINENUM_PATTERN, '#$1'));
-    },
+    }
 
     _handleDiffLegacyRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1374,7 +1382,7 @@
       }
 
       this._normalizeLegacyRouteParams(params);
-    },
+    }
 
     _handleDiffEditRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1387,7 +1395,7 @@
         view: Gerrit.Nav.View.EDIT,
       });
       this.$.reporting.setRepoName(project);
-    },
+    }
 
     _handleChangeEditRoute(ctx) {
       // Parameter order is based on the regex group number matched.
@@ -1400,7 +1408,7 @@
         edit: true,
       });
       this.$.reporting.setRepoName(project);
-    },
+    }
 
     /**
      * Normalize the patch range params for a the change or diff view and
@@ -1413,16 +1421,16 @@
       } else {
         this._setParams(params);
       }
-    },
+    }
 
     _handleAgreementsRoute() {
       this._redirect('/settings/#Agreements');
-    },
+    }
 
     _handleNewAgreementsRoute(data) {
       data.params.view = Gerrit.Nav.View.AGREEMENTS;
       this._setParams(data.params);
-    },
+    }
 
     _handleSettingsLegacyRoute(data) {
       // email tokens may contain '+' but no space.
@@ -1433,11 +1441,11 @@
         view: Gerrit.Nav.View.SETTINGS,
         emailToken: token,
       });
-    },
+    }
 
     _handleSettingsRoute(data) {
       this._setParams({view: Gerrit.Nav.View.SETTINGS});
-    },
+    }
 
     _handleRegisterRoute(ctx) {
       this._setParams({justRegistered: true});
@@ -1448,7 +1456,7 @@
 
       if (path[0] !== '/') { return; }
       this._redirect(this.getBaseUrl() + path);
-    },
+    }
 
     /**
      * Handler for routes that should pass through the router and not be caught
@@ -1456,7 +1464,7 @@
      */
     _handlePassThroughRoute() {
       location.reload();
-    },
+    }
 
     /**
      * URL may sometimes have /+/ encoded to / /.
@@ -1466,26 +1474,26 @@
       let hash = this._getHashFromCanonicalPath(ctx.canonicalPath);
       if (hash.length) { hash = '#' + hash; }
       this._redirect(`/c/${ctx.params[0]}/+/${ctx.params[1]}${hash}`);
-    },
+    }
 
     _handlePluginScreen(ctx) {
       const view = Gerrit.Nav.View.PLUGIN_SCREEN;
       const plugin = ctx.params[0];
       const screen = ctx.params[1];
       this._setParams({view, plugin, screen});
-    },
+    }
 
     _handleDocumentationSearchRoute(data) {
       this._setParams({
         view: Gerrit.Nav.View.DOCUMENTATION_SEARCH,
         filter: data.params.filter || null,
       });
-    },
+    }
 
     _handleDocumentationSearchRedirectRoute(data) {
       this._redirect('/Documentation/q/filter:' +
           encodeURIComponent(data.params[0]));
-    },
+    }
 
     _handleDocumentationRedirectRoute(data) {
       if (data.params[1]) {
@@ -1494,7 +1502,7 @@
         // Redirect /Documentation to /Documentation/index.html
         this._redirect('/Documentation/index.html');
       }
-    },
+    }
 
     /**
      * Catchall route for when no other route is matched.
@@ -1507,7 +1515,7 @@
         // Route can be recognized by server, so we pass it to server.
         this._handlePassThroughRoute();
       }
-    },
+    }
 
     _show404() {
       // Note: the app's 404 display is tightly-coupled with catching 404
@@ -1515,6 +1523,8 @@
       // TODO: Decouple the gr-app error view from network responses.
       this._appElement().dispatchEvent(new CustomEvent('page-error',
           {detail: {response: {status: 404}}}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRouter.is, GrRouter);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
index 4bfc35b..fb7f0d6 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-router</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html
index 0cdef8c..1b57ddb 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.html
@@ -29,11 +29,9 @@
       }
       gr-autocomplete {
         background-color: var(--view-background-color);
-        border: 1px solid var(--border-color);
         border-radius: var(--border-radius);
         flex: 1;
         outline: none;
-        padding: var(--spacing-xs);
       }
     </style>
     <form>
@@ -45,7 +43,6 @@
           on-commit="_handleInputCommit"
           allow-non-suggested-values
           multi
-          borderless
           threshold="[[_threshold]]"
           tab-complete
           vertical-offset="30"></gr-autocomplete>
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
index 6c7b0fd..4ae1f20 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
@@ -90,6 +90,7 @@
     'status:merged',
     'status:open',
     'status:reviewed',
+    'submissionid:',
     'topic:',
     'tr:',
   ];
@@ -102,75 +103,80 @@
 
   const TOKENIZE_REGEX = /(?:[^\s"]+|"[^"]*")+\s*/g;
 
-  Polymer({
-    is: 'gr-search-bar',
-
+  /**
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrSearchBar extends Polymer.mixinBehaviors( [
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-search-bar'; }
     /**
      * Fired when a search is committed
      *
      * @event handle-search
      */
 
-    behaviors: [
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    properties: {
-      value: {
-        type: String,
-        value: '',
-        notify: true,
-        observer: '_valueChanged',
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      query: {
-        type: Function,
-        value() {
-          return this._getSearchSuggestions.bind(this);
+    static get properties() {
+      return {
+        value: {
+          type: String,
+          value: '',
+          notify: true,
+          observer: '_valueChanged',
         },
-      },
-      projectSuggestions: {
-        type: Function,
-        value() {
-          return () => Promise.resolve([]);
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
         },
-      },
-      groupSuggestions: {
-        type: Function,
-        value() {
-          return () => Promise.resolve([]);
+        query: {
+          type: Function,
+          value() {
+            return this._getSearchSuggestions.bind(this);
+          },
         },
-      },
-      accountSuggestions: {
-        type: Function,
-        value() {
-          return () => Promise.resolve([]);
+        projectSuggestions: {
+          type: Function,
+          value() {
+            return () => Promise.resolve([]);
+          },
         },
-      },
-      _inputVal: String,
-      _threshold: {
-        type: Number,
-        value: 1,
-      },
-    },
+        groupSuggestions: {
+          type: Function,
+          value() {
+            return () => Promise.resolve([]);
+          },
+        },
+        accountSuggestions: {
+          type: Function,
+          value() {
+            return () => Promise.resolve([]);
+          },
+        },
+        _inputVal: String,
+        _threshold: {
+          type: Number,
+          value: 1,
+        },
+      };
+    }
 
     keyboardShortcuts() {
       return {
         [this.Shortcut.SEARCH]: '_handleSearch',
       };
-    },
+    }
 
     _valueChanged(value) {
       this._inputVal = value;
-    },
+    }
 
     _handleInputCommit(e) {
       this._preventDefaultAndNavigateToInputVal(e);
-    },
+    }
 
     /**
      * This function is called in a few different cases:
@@ -204,7 +210,7 @@
           detail: {inputVal: this._inputVal},
         }));
       }
-    },
+    }
 
     /**
      * Determine what array of possible suggestions should be provided
@@ -246,7 +252,7 @@
               .filter(operator => operator.includes(input))
               .map(operator => ({text: operator})));
       }
-    },
+    }
 
     /**
      * Get the sorted, pruned list of suggestions for the current search query.
@@ -289,7 +295,7 @@
                   };
                 });
           });
-    },
+    }
 
     _handleSearch(e) {
       const keyboardEvent = this.getKeyboardEvent(e);
@@ -299,6 +305,8 @@
       e.preventDefault();
       this.$.searchInput.focus();
       this.$.searchInput.selectAll();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSearchBar.is, GrSearchBar);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
index a4927c3..c822b73 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-search-bar</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search.js b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search.js
index 7dff30b..03a2c0d 100644
--- a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search.js
+++ b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search.js
@@ -21,52 +21,58 @@
   const SELF_EXPRESSION = 'self';
   const ME_EXPRESSION = 'me';
 
-  Polymer({
-    is: 'gr-smart-search',
+  /**
+    * @appliesMixin Gerrit.DisplayNameMixin
+    */
+  class GrSmartSearch extends Polymer.mixinBehaviors( [
+    Gerrit.DisplayNameBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-smart-search'; }
 
-    properties: {
-      searchQuery: String,
-      _config: Object,
-      _projectSuggestions: {
-        type: Function,
-        value() {
-          return this._fetchProjects.bind(this);
+    static get properties() {
+      return {
+        searchQuery: String,
+        _config: Object,
+        _projectSuggestions: {
+          type: Function,
+          value() {
+            return this._fetchProjects.bind(this);
+          },
         },
-      },
-      _groupSuggestions: {
-        type: Function,
-        value() {
-          return this._fetchGroups.bind(this);
+        _groupSuggestions: {
+          type: Function,
+          value() {
+            return this._fetchGroups.bind(this);
+          },
         },
-      },
-      _accountSuggestions: {
-        type: Function,
-        value() {
-          return this._fetchAccounts.bind(this);
+        _accountSuggestions: {
+          type: Function,
+          value() {
+            return this._fetchAccounts.bind(this);
+          },
         },
-      },
-    },
-
-    behaviors: [
-      Gerrit.DisplayNameBehavior,
-    ],
+      };
+    }
 
     attached() {
+      super.attached();
       this.$.restAPI.getConfig().then(cfg => {
         this._config = cfg;
       });
-    },
+    }
 
     _handleSearch(e) {
       const input = e.detail.inputVal;
       if (input) {
         Gerrit.Nav.navigateToSearchQuery(input);
       }
-    },
+    }
 
     _accountOrAnon(name) {
       return this.getUserName(this._serverConfig, name, false);
-    },
+    }
 
     /**
      * Fetch from the API the predicted projects.
@@ -86,7 +92,7 @@
             const keys = Object.keys(projects);
             return keys.map(key => ({text: predicate + ':' + key}));
           });
-    },
+    }
 
     /**
      * Fetch from the API the predicted groups.
@@ -107,7 +113,7 @@
             const keys = Object.keys(groups);
             return keys.map(key => ({text: predicate + ':' + key}));
           });
-    },
+    }
 
     /**
      * Fetch from the API the predicted accounts.
@@ -138,7 +144,7 @@
               return accounts;
             }
           });
-    },
+    }
 
     _mapAccountsHelper(accounts, predicate) {
       return accounts.map(account => ({
@@ -147,6 +153,8 @@
           `${predicate}:${account.email}` :
           `${predicate}:"${this._accountOrAnon(account)}"`,
       }));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSmartSearch.is, GrSmartSearch);
 })();
diff --git a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html
index 53036dc..5a4e341 100644
--- a/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html
+++ b/polygerrit-ui/app/elements/core/gr-smart-search/gr-smart-search_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-smart-search</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/custom-dark-theme_test.html b/polygerrit-ui/app/elements/custom-dark-theme_test.html
index 4cf35f1..1cd042a 100644
--- a/polygerrit-ui/app/elements/custom-dark-theme_test.html
+++ b/polygerrit-ui/app/elements/custom-dark-theme_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-app-it_test</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/custom-light-theme_test.html b/polygerrit-ui/app/elements/custom-light-theme_test.html
index e346af5..0cabd09 100644
--- a/polygerrit-ui/app/elements/custom-light-theme_test.html
+++ b/polygerrit-ui/app/elements/custom-light-theme_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-app-it_test</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api-mock.js b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api-mock.js
index b7994e6..4009420 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api-mock.js
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api-mock.js
@@ -17,16 +17,20 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'comment-api-mock',
+  class CommentApiMock extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'comment-api-mock'; }
 
-    properties: {
-      _changeComments: Object,
-    },
+    static get properties() {
+      return {
+        _changeComments: Object,
+      };
+    }
 
     loadComments() {
       return this._reloadComments();
-    },
+    }
 
     /**
      * For the purposes of the mock, _reloadDrafts is not included because its
@@ -38,13 +42,15 @@
       return this._reloadComments().then(() => {
         return e.detail.resolve();
       });
-    },
+    }
 
     _reloadComments() {
       return this.$.commentAPI.loadAll(this._changeNum)
           .then(comments => {
             this._changeComments = this.$.commentAPI._changeComments;
           });
-    },
-  });
+    }
+  }
+
+  customElements.define(CommentApiMock.is, CommentApiMock);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.js b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.js
index 1ac307f..e84e996 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.js
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.js
@@ -460,20 +460,27 @@
         this._isInRevisionOfPatchRange(comment, range);
   };
 
-  Polymer({
-    is: 'gr-comment-api',
+  /**
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrCommentApi extends Polymer.mixinBehaviors( [
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-comment-api'; }
 
-    properties: {
-      _changeComments: Object,
-    },
+    static get properties() {
+      return {
+        _changeComments: Object,
+      };
+    }
 
-    listeners: {
-      'reload-drafts': 'reloadDrafts',
-    },
-
-    behaviors: [
-      Gerrit.PatchSetBehavior,
-    ],
+    created() {
+      super.created();
+      this.addEventListener('reload-drafts',
+          changeNum => this.reloadDrafts(changeNum));
+    }
 
     /**
      * Load all comments (with drafts and robot comments) for the given change
@@ -494,7 +501,7 @@
             robotComments, drafts, changeNum);
         return this._changeComments;
       });
-    },
+    }
 
     /**
      * Re-initialize _changeComments with a new ChangeComments object, that
@@ -513,6 +520,8 @@
             this._changeComments.robotComments, drafts, changeNum);
         return this._changeComments;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCommentApi.is, GrCommentApi);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html
index 47181f9..4261c2d 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-comment-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer.js b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer.js
index 3d9c172..d1df4d0 100644
--- a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer.js
@@ -24,20 +24,23 @@
     [Gerrit.CoverageType.NOT_INSTRUMENTED, 'Not instrumented by any tests.'],
   ]);
 
-  Polymer({
-    is: 'gr-coverage-layer',
+  class GrCoverageLayer extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-coverage-layer'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * Must be sorted by code_range.start_line.
        * Must only contain ranges that match the side.
        *
        * @type {!Array<!Gerrit.CoverageRange>}
        */
-      coverageRanges: Array,
-      side: String,
+        coverageRanges: Array,
+        side: String,
 
-      /**
+        /**
        * We keep track of the line number from the previous annotate() call,
        * and also of the index of the coverage range that had matched.
        * annotate() calls are coming in with increasing line numbers and
@@ -45,15 +48,16 @@
        * and efficient way for finding the coverage range that matches a given
        * line number.
        */
-      _lineNumber: {
-        type: Number,
-        value: 0,
-      },
-      _index: {
-        type: Number,
-        value: 0,
-      },
-    },
+        _lineNumber: {
+          type: Number,
+          value: 0,
+        },
+        _index: {
+          type: Number,
+          value: 0,
+        },
+      };
+    }
 
     /**
      * Layer method to add annotations to a line.
@@ -102,6 +106,8 @@
         lineNumberEl.title = TOOLTIP_MAP.get(coverageRange.type);
         return;
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCoverageLayer.is, GrCoverageLayer);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html
index 45a67e1..99c583d 100644
--- a/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-coverage-layer/gr-coverage-layer_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-coverage-layer</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html
index 19e017d..4c44414 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>GrDiffBuilderUnified</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index 56fb8f5..758798a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-builder</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
index 67c562c..039a99fa 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
@@ -35,33 +35,36 @@
   const LEFT_SIDE_CLASS = 'target-side-left';
   const RIGHT_SIDE_CLASS = 'target-side-right';
 
-  Polymer({
-    is: 'gr-diff-cursor',
+  class GrDiffCursor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-diff-cursor'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * Either DiffSides.LEFT or DiffSides.RIGHT.
        */
-      side: {
-        type: String,
-        value: DiffSides.RIGHT,
-      },
-      /** @type {!HTMLElement|undefined} */
-      diffRow: {
-        type: Object,
-        notify: true,
-        observer: '_rowChanged',
-      },
+        side: {
+          type: String,
+          value: DiffSides.RIGHT,
+        },
+        /** @type {!HTMLElement|undefined} */
+        diffRow: {
+          type: Object,
+          notify: true,
+          observer: '_rowChanged',
+        },
 
-      /**
+        /**
        * The diff views to cursor through and listen to.
        */
-      diffs: {
-        type: Array,
-        value() { return []; },
-      },
+        diffs: {
+          type: Array,
+          value() { return []; },
+        },
 
-      /**
+        /**
        * If set, the cursor will attempt to move to the line number (instead of
        * the first chunk) the next time the diff renders. It is set back to null
        * when used. It should be only used if you want the line to be focused
@@ -71,56 +74,61 @@
        *
        * @type (?number)
        */
-      initialLineNumber: {
-        type: Number,
-        value: null,
-      },
+        initialLineNumber: {
+          type: Number,
+          value: null,
+        },
 
-      /**
+        /**
        * The scroll behavior for the cursor. Values are 'never' and
        * 'keep-visible'. 'keep-visible' will only scroll if the cursor is beyond
        * the viewport.
        */
-      _scrollBehavior: {
-        type: String,
-        value: ScrollBehavior.KEEP_VISIBLE,
-      },
+        _scrollBehavior: {
+          type: String,
+          value: ScrollBehavior.KEEP_VISIBLE,
+        },
 
-      _focusOnMove: {
-        type: Boolean,
-        value: true,
-      },
+        _focusOnMove: {
+          type: Boolean,
+          value: true,
+        },
 
-      _listeningForScroll: Boolean,
-    },
+        _listeningForScroll: Boolean,
+      };
+    }
 
-    observers: [
-      '_updateSideClass(side)',
-      '_diffsChanged(diffs.splices)',
-    ],
+    static get observers() {
+      return [
+        '_updateSideClass(side)',
+        '_diffsChanged(diffs.splices)',
+      ];
+    }
 
     attached() {
+      super.attached();
       // Catch when users are scrolling as the view loads.
       this.listen(window, 'scroll', '_handleWindowScroll');
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'scroll', '_handleWindowScroll');
-    },
+    }
 
     moveLeft() {
       this.side = DiffSides.LEFT;
       if (this._isTargetBlank()) {
         this.moveUp();
       }
-    },
+    }
 
     moveRight() {
       this.side = DiffSides.RIGHT;
       if (this._isTargetBlank()) {
         this.moveUp();
       }
-    },
+    }
 
     moveDown() {
       if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
@@ -128,7 +136,7 @@
       } else {
         this.$.cursorManager.next();
       }
-    },
+    }
 
     moveUp() {
       if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE) {
@@ -136,7 +144,7 @@
       } else {
         this.$.cursorManager.previous();
       }
-    },
+    }
 
     moveToNextChunk(opt_clipToTop) {
       this.$.cursorManager.next(this._isFirstRowOfChunk.bind(this),
@@ -144,22 +152,22 @@
             return target.parentNode.scrollHeight;
           }, opt_clipToTop);
       this._fixSide();
-    },
+    }
 
     moveToPreviousChunk() {
       this.$.cursorManager.previous(this._isFirstRowOfChunk.bind(this));
       this._fixSide();
-    },
+    }
 
     moveToNextCommentThread() {
       this.$.cursorManager.next(this._rowHasThread.bind(this));
       this._fixSide();
-    },
+    }
 
     moveToPreviousCommentThread() {
       this.$.cursorManager.previous(this._rowHasThread.bind(this));
       this._fixSide();
-    },
+    }
 
     /**
      * @param {number} number
@@ -172,7 +180,7 @@
         this.side = side;
         this.$.cursorManager.setCursor(row);
       }
-    },
+    }
 
     /**
      * Get the line number element targeted by the cursor row and side.
@@ -190,7 +198,7 @@
       }
 
       return this.diffRow.querySelector(lineElSelector);
-    },
+    }
 
     getTargetDiffElement() {
       if (!this.diffRow) return null;
@@ -202,12 +210,12 @@
         return hostOwner.host;
       }
       return null;
-    },
+    }
 
     moveToFirstChunk() {
       this.$.cursorManager.moveToStart();
       this.moveToNextChunk(true);
-    },
+    }
 
     reInitCursor() {
       this._updateStops();
@@ -217,7 +225,7 @@
       } else {
         this.moveToFirstChunk();
       }
-    },
+    }
 
     _handleWindowScroll() {
       if (this._listeningForScroll) {
@@ -225,7 +233,7 @@
         this._focusOnMove = false;
         this._listeningForScroll = false;
       }
-    },
+    }
 
     handleDiffUpdate() {
       this._updateStops();
@@ -240,11 +248,25 @@
       this._scrollBehavior = ScrollBehavior.KEEP_VISIBLE;
       this._focusOnMove = true;
       this._listeningForScroll = false;
-    },
+    }
 
     _handleDiffRenderStart() {
       this._listeningForScroll = true;
-    },
+    }
+
+    createCommentInPlace() {
+      const diffWithRangeSelected = this.diffs.find(diff => {
+        return diff.isRangeSelected();
+      });
+      if (diffWithRangeSelected) {
+        diffWithRangeSelected.createRangeComment();
+      } else {
+        const line = this.getTargetLineElement();
+        if (line) {
+          this.getTargetDiffElement().addDraftAtLine(line);
+        }
+      }
+    }
 
     /**
      * Get an object describing the location of the cursor. Such as
@@ -276,7 +298,7 @@
         leftSide: cell.matches('.left'),
         number: parseInt(number, 10),
       };
-    },
+    }
 
     _getViewMode() {
       if (!this.diffRow) {
@@ -288,24 +310,24 @@
       } else {
         return DiffViewMode.UNIFIED;
       }
-    },
+    }
 
     _rowHasSide(row) {
       const selector = (this.side === DiffSides.LEFT ? '.left' : '.right') +
           ' + .content';
       return !!row.querySelector(selector);
-    },
+    }
 
     _isFirstRowOfChunk(row) {
       const parentClassList = row.parentNode.classList;
       return parentClassList.contains('section') &&
           parentClassList.contains('delta') &&
           !row.previousSibling;
-    },
+    }
 
     _rowHasThread(row) {
       return row.querySelector('.thread-group');
-    },
+    }
 
     /**
      * If we jumped to a row where there is no content on the current side then
@@ -317,7 +339,7 @@
         this.side = this.side === DiffSides.LEFT ?
           DiffSides.RIGHT : DiffSides.LEFT;
       }
-    },
+    }
 
     _isTargetBlank() {
       if (!this.diffRow) {
@@ -327,14 +349,14 @@
       const actions = this._getActionsForRow();
       return (this.side === DiffSides.LEFT && !actions.left) ||
           (this.side === DiffSides.RIGHT && !actions.right);
-    },
+    }
 
     _rowChanged(newRow, oldRow) {
       if (oldRow) {
         oldRow.classList.remove(LEFT_SIDE_CLASS, RIGHT_SIDE_CLASS);
       }
       this._updateSideClass();
-    },
+    }
 
     _updateSideClass() {
       if (!this.diffRow) {
@@ -344,11 +366,11 @@
           this.diffRow);
       this.toggleClass(RIGHT_SIDE_CLASS, this.side === DiffSides.RIGHT,
           this.diffRow);
-    },
+    }
 
     _isActionType(type) {
       return type !== 'blank' && type !== 'contextControl';
-    },
+    }
 
     _getActionsForRow() {
       const actions = {left: false, right: false};
@@ -359,18 +381,18 @@
             this.diffRow.getAttribute('right-type'));
       }
       return actions;
-    },
+    }
 
     _getStops() {
       return this.diffs.reduce(
           (stops, diff) => {
             return stops.concat(diff.getCursorStops());
           }, []);
-    },
+    }
 
     _updateStops() {
       this.$.cursorManager.stops = this._getStops();
-    },
+    }
 
     /**
      * Setup and tear down on-render listeners for any diffs that are added or
@@ -406,7 +428,7 @@
               'render-content', 'handleDiffUpdate');
         }
       }
-    },
+    }
 
     _findRowByNumberAndFile(targetNumber, side, opt_path) {
       let stops;
@@ -423,6 +445,8 @@
           return stops[i];
         }
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffCursor.is, GrDiffCursor);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
index 1c1100d..626ab33 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-cursor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -259,6 +259,70 @@
       );
     });
 
+    suite('createCommentInPlace', () => {
+      setup(() => {
+        diffElement.loggedIn = true;
+      });
+
+      test('adds new draft for selected line on the left', done => {
+        cursorElement.moveToLineNumber(2, 'left');
+        diffElement.addEventListener('create-comment', e => {
+          const {lineNum, range, side, patchNum} = e.detail;
+          assert.equal(lineNum, 2);
+          assert.equal(range, undefined);
+          assert.equal(patchNum, 1);
+          assert.equal(side, 'left');
+          done();
+        });
+        cursorElement.createCommentInPlace();
+      });
+
+      test('adds draft for selected line on the right', done => {
+        cursorElement.moveToLineNumber(4, 'right');
+        diffElement.addEventListener('create-comment', e => {
+          const {lineNum, range, side, patchNum} = e.detail;
+          assert.equal(lineNum, 4);
+          assert.equal(range, undefined);
+          assert.equal(patchNum, 2);
+          assert.equal(side, 'right');
+          done();
+        });
+        cursorElement.createCommentInPlace();
+      });
+
+      test('createCommentInPlace creates comment for range if selected', done => {
+        const someRange = {
+          start_line: 2,
+          start_character: 3,
+          end_line: 6,
+          end_character: 1,
+        };
+        diffElement.$.highlights.selectedRange = {
+          side: 'right',
+          range: someRange,
+        };
+        diffElement.addEventListener('create-comment', e => {
+          const {lineNum, range, side, patchNum} = e.detail;
+          assert.equal(lineNum, 6);
+          assert.equal(range, someRange);
+          assert.equal(patchNum, 2);
+          assert.equal(side, 'right');
+          done();
+        });
+        cursorElement.createCommentInPlace();
+      });
+
+      test('createCommentInPlace ignores call if nothing is selected', () => {
+        const createRangeCommentStub = sandbox.stub(diffElement,
+            'createRangeComment');
+        const addDraftAtLineStub = sandbox.stub(diffElement, 'addDraftAtLine');
+        cursorElement.diffRow = undefined;
+        cursorElement.createCommentInPlace();
+        assert.isFalse(createRangeCommentStub.called);
+        assert.isFalse(addDraftAtLineStub.called);
+      });
+    });
+
     test('getAddress', () => {
       // It should initialize to the first chunk: line 5 of the revision.
       assert.deepEqual(cursorElement.getAddress(),
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation.js
index c1d53aa..c729bcb 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation.js
@@ -43,6 +43,65 @@
     },
 
     /**
+     * Annotates the [offset, offset+length) text segment in the parent with the
+     * element definition provided as arguments.
+     *
+     * @param {!Element} parent the node whose contents will be annotated.
+     * @param {number} offset the 0-based offset from which the annotation will
+     *   start.
+     * @param {number} length of the annotated text.
+     * @param {GrAnnotation.ElementSpec} elementSpec the spec to create the
+     *   annotating element.
+     */
+    annotateWithElement(parent, offset, length, {tagName, attributes = {}}) {
+      let childNodes;
+
+      if (parent instanceof Element) {
+        childNodes = Array.from(parent.childNodes);
+      } else if (parent instanceof Text) {
+        childNodes = [parent];
+        parent = parent.parentNode;
+      } else {
+        return;
+      }
+
+      const nestedNodes = [];
+      for (let node of childNodes) {
+        const initialNodeLength = this.getLength(node);
+        // If the current node is completely before the offset.
+        if (offset > 0 && initialNodeLength <= offset) {
+          offset -= initialNodeLength;
+          continue;
+        }
+
+        if (offset > 0) {
+          node = this.splitNode(node, offset);
+          offset = 0;
+        }
+        if (this.getLength(node) > length) {
+          this.splitNode(node, length);
+        }
+        nestedNodes.push(node);
+
+        length -= this.getLength(node);
+        if (!length) break;
+      }
+
+      const wrapper = document.createElement(tagName);
+      const sanitizer = window.Polymer.sanitizeDOMValue;
+      for (const [name, value] of Object.entries(attributes)) {
+        wrapper.setAttribute(
+            name, sanitizer
+              ? sanitizer(value, name, 'attribute', wrapper)
+              : value);
+      }
+      for (const inner of nestedNodes) {
+        parent.replaceChild(wrapper, inner);
+        wrapper.appendChild(inner);
+      }
+    },
+
+    /**
      * Surrounds the element's text at specified range in an ANNOTATION_TAG
      * element. If the element has child elements, the range is split and
      * applied as deeply as possible.
@@ -210,5 +269,15 @@
     },
   };
 
+  /**
+   * Data used to construct an element.
+   *
+   * @typedef {{
+   *   tagName: string,
+   *   attributes: (!Object<string, *>|undefined)
+   * }}
+   */
+  GrAnnotation.ElementSpec;
+
   window.GrAnnotation = GrAnnotation;
 })(window);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html
index c1bf3ed..a2c271b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-annotation_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-annotation</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -40,13 +40,19 @@
     let str;
     let parent;
     let textNode;
+    let sandbox;
 
     setup(() => {
+      sandbox = sinon.sandbox.create();
       parent = fixture('basic');
       textNode = parent.childNodes[0];
       str = textNode.textContent;
     });
 
+    teardown(() => {
+      sandbox.restore();
+    });
+
     test('_annotateText Case 1', () => {
       GrAnnotation._annotateText(textNode, 0, str.length, 'foobar');
 
@@ -191,5 +197,95 @@
       assert(node.textContent, helloString);
       assert(tail.textContent, unicodeString);
     });
+
+    suite('annotateWithElement', () => {
+      const fullText = '01234567890123456789';
+      let mockSanitize;
+
+      setup(() => {
+        mockSanitize = sandbox.spy(window.Polymer, 'sanitizeDOMValue');
+      });
+
+      test('annotates when fully contained', () => {
+        const length = 10;
+        const container = document.createElement('div');
+        container.textContent = fullText;
+        GrAnnotation.annotateWithElement(
+            container, 1, length, {tagName: 'test-wrapper'});
+
+        assert.equal(
+            container.innerHTML,
+            '0<test-wrapper>1234567890</test-wrapper>123456789');
+      });
+
+      test('annotates when spanning multiple nodes', () => {
+        const length = 10;
+        const container = document.createElement('div');
+        container.textContent = fullText;
+        GrAnnotation.annotateElement(container, 5, length, 'testclass');
+        GrAnnotation.annotateWithElement(
+            container, 1, length, {tagName: 'test-wrapper'});
+
+        assert.equal(
+            container.innerHTML,
+            '0'
+              + '<test-wrapper>'
+              + '1234'
+              + '<hl class="testclass">567890</hl>'
+              + '</test-wrapper>'
+              + '<hl class="testclass">1234</hl>'
+              + '56789');
+      });
+
+      test('annotates text node', () => {
+        const length = 10;
+        const container = document.createElement('div');
+        container.textContent = fullText;
+        GrAnnotation.annotateWithElement(
+            container.childNodes[0], 1, length, {tagName: 'test-wrapper'});
+
+        assert.equal(
+            container.innerHTML,
+            '0<test-wrapper>1234567890</test-wrapper>123456789');
+      });
+
+      test('handles zero-length nodes', () => {
+        const container = document.createElement('div');
+        container.appendChild(document.createTextNode('0123456789'));
+        container.appendChild(document.createElement('span'));
+        container.appendChild(document.createTextNode('0123456789'));
+        GrAnnotation.annotateWithElement(
+            container, 1, 10, {tagName: 'test-wrapper'});
+
+        assert.equal(
+            container.innerHTML,
+            '0<test-wrapper>123456789<span></span>0</test-wrapper>123456789');
+      });
+
+      test('sets sanitized attributes', () => {
+        const container = document.createElement('div');
+        container.textContent = fullText;
+        const attributes = {
+          'href': 'foo',
+          'data-foo': 'bar',
+          'class': 'hello world',
+        };
+        GrAnnotation.annotateWithElement(
+            container, 1, length, {tagName: 'test-wrapper', attributes});
+        assert(mockSanitize.calledWith(
+            'foo', 'href', 'attribute', sinon.match.instanceOf(Element)));
+        assert(mockSanitize.calledWith(
+            'bar', 'data-foo', 'attribute', sinon.match.instanceOf(Element)));
+        assert(mockSanitize.calledWith(
+            'hello world',
+            'class',
+            'attribute',
+            sinon.match.instanceOf(Element)));
+        const el = container.querySelector('test-wrapper');
+        assert.equal(el.getAttribute('href'), 'foo');
+        assert.equal(el.getAttribute('data-foo'), 'bar');
+        assert.equal(el.getAttribute('class'), 'hello world');
+      });
+    });
   });
 </script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index 4b145c6..88d19aa 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -17,33 +17,55 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-diff-highlight',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrDiffHighlight extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff-highlight'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {!Array<!Gerrit.HoveredRange>} */
-      commentRanges: {
-        type: Array,
-        notify: true,
-      },
-      loggedIn: Boolean,
-      /**
+        commentRanges: {
+          type: Array,
+          notify: true,
+        },
+        loggedIn: Boolean,
+        /**
        * querySelector can return null, so needs to be nullable.
        *
        * @type {?HTMLElement}
        * */
-      _cachedDiffBuilder: Object,
-    },
+        _cachedDiffBuilder: Object,
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+        /**
+       * Which range is currently selected by the user.
+       * Stored in order to add a range-based comment
+       * later.
+       * undefined if no range is selected.
+       *
+       * @type {{side: string, range: Gerrit.Range}|undefined}
+       */
+        selectedRange: {
+          type: Object,
+          notify: true,
+        },
+      };
+    }
 
-    listeners: {
-      'comment-thread-mouseleave': '_handleCommentThreadMouseleave',
-      'comment-thread-mouseenter': '_handleCommentThreadMouseenter',
-      'create-range-comment': '_createRangeComment',
-    },
+    created() {
+      super.created();
+      this.addEventListener('comment-thread-mouseleave',
+          e => this._handleCommentThreadMouseleave(e));
+      this.addEventListener('comment-thread-mouseenter',
+          e => this._handleCommentThreadMouseenter(e));
+      this.addEventListener('create-comment-requested',
+          e => this._handleRangeCommentRequest(e));
+    }
 
     get diffBuilder() {
       if (!this._cachedDiffBuilder) {
@@ -51,11 +73,7 @@
             Polymer.dom(this).querySelector('gr-diff-builder');
       }
       return this._cachedDiffBuilder;
-    },
-
-    isRangeSelected() {
-      return !!this.$$('gr-selection-action-box');
-    },
+    }
 
     /**
      * Determines side/line/range for a DOM selection and shows a tooltip.
@@ -84,7 +102,7 @@
       this.debounce(
           'selectionChange', () => this._handleSelection(selection, isMouseUp),
           10);
-    },
+    }
 
     _getThreadEl(e) {
       const path = Polymer.dom(e).path || [];
@@ -92,7 +110,7 @@
         if (pathEl.classList.contains('comment-thread')) return pathEl;
       }
       return null;
-    },
+    }
 
     _handleCommentThreadMouseenter(e) {
       const threadEl = this._getThreadEl(e);
@@ -101,7 +119,7 @@
       if (index !== undefined) {
         this.set(['commentRanges', index, 'hovering'], true);
       }
-    },
+    }
 
     _handleCommentThreadMouseleave(e) {
       const threadEl = this._getThreadEl(e);
@@ -110,7 +128,7 @@
       if (index !== undefined) {
         this.set(['commentRanges', index, 'hovering'], false);
       }
-    },
+    }
 
     _indexForThreadEl(threadEl) {
       const side = threadEl.getAttribute('comment-side');
@@ -119,7 +137,7 @@
       if (!range) return undefined;
 
       return this._indexOfCommentRange(side, range);
-    },
+    }
 
     _indexOfCommentRange(side, range) {
       function rangesEqual(a, b) {
@@ -137,7 +155,7 @@
 
       return this.commentRanges.findIndex(commentRange =>
         commentRange.side === side && rangesEqual(commentRange.range, range));
-    },
+    }
 
     /**
      * Get current normalized selection.
@@ -175,7 +193,7 @@
           end: endRange.end,
         };
       }
-    },
+    }
 
     /**
      * Normalize a specific DOM Range.
@@ -189,7 +207,7 @@
         end: this._normalizeSelectionSide(
             range.endContainer, range.endOffset),
       }, domRange);
-    },
+    }
 
     /**
      * Adjust triple click selection for the whole line.
@@ -230,7 +248,7 @@
         };
       }
       return range;
-    },
+    }
 
     /**
      * Convert DOM Range selection to concrete numbers (line, column, side).
@@ -287,7 +305,7 @@
         line,
         column,
       };
-    },
+    }
 
     /**
      * The only line in which add a comment tooltip is cut off is the first
@@ -303,7 +321,7 @@
       }
       actionBox.positionBelow = true;
       actionBox.placeBelow(range);
-    },
+    }
 
     _isRangeValid(range) {
       if (!range || !range.start || !range.end) {
@@ -317,7 +335,7 @@
         return false;
       }
       return true;
-    },
+    }
 
     _handleSelection(selection, isMouseUp) {
       const normalizedRange = this._getNormalizedRange(selection);
@@ -350,12 +368,12 @@
         // is empty to see that it's at the end of a line.
         const content = domRange.cloneContents().querySelector('.contentText');
         if (isMouseUp && this._getLength(content) === 0) {
-          this.fire('create-range-comment', {side: start.side, range: {
+          this._fireCreateRangeComment(start.side, {
             start_line: start.line,
             start_character: 0,
             end_line: start.line,
             end_character: start.column,
-          }});
+          });
         }
         return;
       }
@@ -366,13 +384,15 @@
         const root = Polymer.dom(this.root);
         root.insertBefore(actionBox, root.firstElementChild);
       }
-      actionBox.range = {
-        start_line: start.line,
-        start_character: start.column,
-        end_line: end.line,
-        end_character: end.column,
+      this.selectedRange = {
+        range: {
+          start_line: start.line,
+          start_character: start.column,
+          end_line: end.line,
+          end_character: end.column,
+        },
+        side: start.side,
       };
-      actionBox.side = start.side;
       if (start.line === end.line) {
         this._positionActionBox(actionBox, start.line, domRange);
       } else if (start.node instanceof Text) {
@@ -387,18 +407,29 @@
       } else {
         this._positionActionBox(actionBox, start.line, start.node);
       }
-    },
+    }
 
-    _createRangeComment(e) {
+    _fireCreateRangeComment(side, range) {
+      this.fire('create-range-comment', {side, range});
       this._removeActionBox();
-    },
+    }
+
+    _handleRangeCommentRequest(e) {
+      e.stopPropagation();
+      if (!this.selectedRange) {
+        throw Error('Selected Range is needed for new range comment!');
+      }
+      const {side, range} = this.selectedRange;
+      this._fireCreateRangeComment(side, range);
+    }
 
     _removeActionBox() {
+      this.selectedRange = undefined;
       const actionBox = this.$$('gr-selection-action-box');
       if (actionBox) {
         Polymer.dom(this.root).removeChild(actionBox);
       }
-    },
+    }
 
     _convertOffsetToColumn(el, offset) {
       if (el instanceof Element && el.classList.contains('content')) {
@@ -414,7 +445,7 @@
         }
       }
       return offset;
-    },
+    }
 
     /**
      * Traverse Element from right to left, call callback for each node.
@@ -439,7 +470,7 @@
         }
         node = nextNode;
       }
-    },
+    }
 
     /**
      * Get length of a node. If the node is a content node, then only give the
@@ -454,6 +485,8 @@
       } else {
         return GrAnnotation.getLength(node);
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffHighlight.is, GrDiffHighlight);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
index c929e1e..3de521d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-highlight</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -228,13 +228,25 @@
         assert.isFalse(element.set.called);
       });
 
-      test('on create-range-comment action box is removed', () => {
+      test(`create-range-comment for range when create-comment-requested
+            is fired`, () => {
         sandbox.stub(element, '_removeActionBox');
-        element.fire('create-range-comment', {
-          comment: {
-            range: {},
+        element.selectedRange = {
+          side: 'left',
+          range: {
+            start_line: 7,
+            start_character: 11,
+            end_line: 24,
+            end_character: 42,
           },
+        };
+        const requestEvent = new CustomEvent('create-comment-requested');
+        let createRangeEvent;
+        element.addEventListener('create-range-comment', e => {
+          createRangeEvent = e;
         });
+        element.dispatchEvent(requestEvent);
+        assert.deepEqual(element.selectedRange, createRangeEvent.detail);
         assert.isTrue(element._removeActionBox.called);
       });
     });
@@ -271,14 +283,6 @@
         element._handleSelection(selection);
       };
 
-      const getActionRange = () =>
-        Polymer.dom(element.root).querySelector(
-            'gr-selection-action-box').range;
-
-      const getActionSide = () =>
-        Polymer.dom(element.root).querySelector(
-            'gr-selection-action-box').side;
-
       const getLineElByChild = node => {
         const stubs = contentStubs.find(stub => stub.contentTd.contains(node));
         return stubs && stubs.lineEl;
@@ -329,14 +333,14 @@
         sandbox.spy(element, '_positionActionBox');
         emulateSelection(content.firstChild, 5, content.firstChild, 12);
         const actionBox = element.$$('gr-selection-action-box');
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 138,
           start_character: 5,
           end_line: 138,
           end_character: 12,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
         assert.notOk(actionBox.positionBelow);
       });
 
@@ -346,16 +350,15 @@
         sandbox.spy(element, '_positionActionBox');
         emulateSelection(
             startContent.firstChild, 10, endContent.lastChild, 7);
-        assert.isTrue(element.isRangeSelected());
         const actionBox = element.$$('gr-selection-action-box');
-
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 119,
           start_character: 10,
           end_line: 120,
           end_character: 36,
         });
-        assert.equal(getActionSide(), 'right');
+        assert.equal(side, 'right');
         assert.notOk(actionBox.positionBelow);
       });
 
@@ -381,8 +384,8 @@
           removeAllRanges: sandbox.stub(),
         };
         element._handleSelection(selection);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 119,
           start_character: 10,
           end_line: 120,
@@ -394,43 +397,43 @@
         const startContent = stubContent(119, 'right');
         const endContent = stubContent(120, 'right');
         emulateSelection(startContent.firstChild, 10, endContent.firstChild, 2);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 119,
           start_character: 10,
           end_line: 120,
           end_character: 2,
         });
-        assert.equal(getActionSide(), 'right');
+        assert.equal(side, 'right');
       });
 
       test('collapsed', () => {
         const content = stubContent(138, 'left');
         emulateSelection(content.firstChild, 5, content.firstChild, 5);
         assert.isOk(window.getSelection().getRangeAt(0).startContainer);
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('starts inside hl', () => {
         const content = stubContent(140, 'left');
         const hl = content.querySelector('.foo');
         emulateSelection(hl.firstChild, 2, hl.nextSibling, 7);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 8,
           end_line: 140,
           end_character: 23,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('ends inside hl', () => {
         const content = stubContent(140, 'left');
         const hl = content.querySelector('.bar');
         emulateSelection(hl.previousSibling, 2, hl.firstChild, 3);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 18,
           end_line: 140,
@@ -442,14 +445,14 @@
         const content = stubContent(140, 'left');
         const hl = content.querySelectorAll('hl')[4];
         emulateSelection(content.firstChild, 2, hl.firstChild, 2);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 2,
           end_line: 140,
           end_character: 61,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('starts outside of diff', () => {
@@ -458,21 +461,21 @@
 
         emulateSelection(contentTd.previousElementSibling, 0,
             contentText.firstChild, 2);
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('ends outside of diff', () => {
         const content = stubContent(140, 'left');
         emulateSelection(content.nextElementSibling.firstChild, 2,
             content.firstChild, 2);
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('starts and ends on different sides', () => {
         const startContent = stubContent(140, 'left');
         const endContent = stubContent(130, 'right');
         emulateSelection(startContent.firstChild, 2, endContent.firstChild, 2);
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('starts in comment thread element', () => {
@@ -481,14 +484,14 @@
             '.comment-thread');
         const endContent = stubContent(141, 'left');
         emulateSelection(comment.firstChild, 2, endContent.firstChild, 4);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 83,
           end_line: 141,
           end_character: 4,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('ends in comment thread element', () => {
@@ -496,14 +499,14 @@
         const comment = content.parentElement.querySelector(
             '.comment-thread');
         emulateSelection(content.firstChild, 4, comment.firstChild, 1);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 4,
           end_line: 140,
           end_character: 83,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('starts in context element', () => {
@@ -512,7 +515,7 @@
         const content = stubContent(146, 'right');
         emulateSelection(contextControl, 0, content.firstChild, 7);
         // TODO (viktard): Select nearest line.
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('ends in context element', () => {
@@ -521,35 +524,35 @@
         const content = stubContent(141, 'left');
         emulateSelection(content.firstChild, 2, contextControl, 1);
         // TODO (viktard): Select nearest line.
-        assert.isFalse(element.isRangeSelected());
+        assert.isFalse(!!element.selectedRange);
       });
 
       test('selection containing context element', () => {
         const startContent = stubContent(130, 'right');
         const endContent = stubContent(146, 'right');
         emulateSelection(startContent.firstChild, 3, endContent.firstChild, 14);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 130,
           start_character: 3,
           end_line: 146,
           end_character: 14,
         });
-        assert.equal(getActionSide(), 'right');
+        assert.equal(side, 'right');
       });
 
       test('ends at a tab', () => {
         const content = stubContent(140, 'left');
         emulateSelection(
             content.firstChild, 1, content.querySelector('span'), 0);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 1,
           end_line: 140,
           end_character: 51,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('starts at a tab', () => {
@@ -557,14 +560,14 @@
         emulateSelection(
             content.querySelectorAll('hl')[3], 0,
             content.querySelectorAll('span')[1].nextSibling, 1);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 140,
           start_character: 51,
           end_line: 140,
           end_character: 71,
         });
-        assert.equal(getActionSide(), 'left');
+        assert.equal(side, 'left');
       });
 
       test('properly accounts for syntax highlighting', () => {
@@ -593,14 +596,14 @@
         const startContent = stubContent(119, 'right');
         const endContent = stubContent(120, 'right');
         emulateSelection(startContent.firstChild, 0, endContent.firstChild, 0);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 119,
           start_character: 0,
           end_line: 119,
           end_character: element._getLength(startContent),
         });
-        assert.equal(getActionSide(), 'right');
+        assert.equal(side, 'right');
       });
 
       test('_fixTripleClickSelection empty line', () => {
@@ -608,14 +611,14 @@
         const endContent = stubContent(165, 'left');
         emulateSelection(startContent.firstChild, 0,
             endContent.parentElement.previousElementSibling, 0);
-        assert.isTrue(element.isRangeSelected());
-        assert.deepEqual(getActionRange(), {
+        const {range, side} = element.selectedRange;
+        assert.deepEqual(range, {
           start_line: 146,
           start_character: 0,
           end_line: 146,
           end_character: 84,
         });
-        assert.equal(getActionSide(), 'right');
+        assert.equal(side, 'right');
       });
     });
   });
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
index 6167e88..f5dc438 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
@@ -69,14 +69,22 @@
   };
 
   /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  /**
    * Wrapper around gr-diff.
    *
    * Webcomponent fetching diffs and related data from restAPI and passing them
    * to the presentational gr-diff for rendering.
    */
-  Polymer({
-    is: 'gr-diff-host',
-
+  class GrDiffHost extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff-host'; }
     /**
      * Fired when the user selects a line.
      * @event line-selected
@@ -94,182 +102,191 @@
      * @event diff-comments-modified
      */
 
-    properties: {
-      changeNum: String,
-      noAutoRender: {
-        type: Boolean,
-        value: false,
-      },
-      /** @type {?} */
-      patchRange: Object,
-      path: String,
-      prefs: {
-        type: Object,
-      },
-      projectName: String,
-      displayLine: {
-        type: Boolean,
-        value: false,
-      },
-      isImageDiff: {
-        type: Boolean,
-        computed: '_computeIsImageDiff(diff)',
-        notify: true,
-      },
-      commitRange: Object,
-      filesWeblinks: {
-        type: Object,
-        value() {
-          return {};
+    static get properties() {
+      return {
+        changeNum: String,
+        noAutoRender: {
+          type: Boolean,
+          value: false,
         },
-        notify: true,
-      },
-      hidden: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-      noRenderOnPrefsChange: {
-        type: Boolean,
-        value: false,
-      },
-      comments: {
-        type: Object,
-        observer: '_commentsChanged',
-      },
-      lineWrapping: {
-        type: Boolean,
-        value: false,
-      },
-      viewMode: {
-        type: String,
-        value: DiffViewMode.SIDE_BY_SIDE,
-      },
+        /** @type {?} */
+        patchRange: Object,
+        path: String,
+        prefs: {
+          type: Object,
+        },
+        projectName: String,
+        displayLine: {
+          type: Boolean,
+          value: false,
+        },
+        isImageDiff: {
+          type: Boolean,
+          computed: '_computeIsImageDiff(diff)',
+          notify: true,
+        },
+        commitRange: Object,
+        filesWeblinks: {
+          type: Object,
+          value() {
+            return {};
+          },
+          notify: true,
+        },
+        hidden: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+        noRenderOnPrefsChange: {
+          type: Boolean,
+          value: false,
+        },
+        comments: {
+          type: Object,
+          observer: '_commentsChanged',
+        },
+        lineWrapping: {
+          type: Boolean,
+          value: false,
+        },
+        viewMode: {
+          type: String,
+          value: DiffViewMode.SIDE_BY_SIDE,
+        },
 
-      /**
+        /**
        * Special line number which should not be collapsed into a shared region.
        * @type {{
        *  number: number,
        *  leftSide: {boolean}
        * }|null}
        */
-      lineOfInterest: Object,
+        lineOfInterest: Object,
 
-      /**
+        /**
        * If the diff fails to load, show the failure message in the diff rather
        * than bubbling the error up to the whole page. This is useful for when
        * loading inline diffs because one diff failing need not mark the whole
        * page with a failure.
        */
-      showLoadFailure: Boolean,
+        showLoadFailure: Boolean,
 
-      isBlameLoaded: {
-        type: Boolean,
-        notify: true,
-        computed: '_computeIsBlameLoaded(_blame)',
-      },
+        isBlameLoaded: {
+          type: Boolean,
+          notify: true,
+          computed: '_computeIsBlameLoaded(_blame)',
+        },
 
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
 
-      _loading: {
-        type: Boolean,
-        value: false,
-      },
+        _loading: {
+          type: Boolean,
+          value: false,
+        },
 
-      /** @type {?string} */
-      _errorMessage: {
-        type: String,
-        value: null,
-      },
+        /** @type {?string} */
+        _errorMessage: {
+          type: String,
+          value: null,
+        },
 
-      /** @type {?Object} */
-      _baseImage: Object,
-      /** @type {?Object} */
-      _revisionImage: Object,
-      /**
+        /** @type {?Object} */
+        _baseImage: Object,
+        /** @type {?Object} */
+        _revisionImage: Object,
+        /**
        * This is a DiffInfo object.
        */
-      diff: {
-        type: Object,
-        notify: true,
-      },
+        diff: {
+          type: Object,
+          notify: true,
+        },
 
-      /** @type {?Object} */
-      _blame: {
-        type: Object,
-        value: null,
-      },
+        /** @type {?Object} */
+        _blame: {
+          type: Object,
+          value: null,
+        },
 
-      /**
+        /**
        * @type {!Array<!Gerrit.CoverageRange>}
        */
-      _coverageRanges: {
-        type: Array,
-        value: () => [],
-      },
+        _coverageRanges: {
+          type: Array,
+          value: () => [],
+        },
 
-      _loadedWhitespaceLevel: String,
+        _loadedWhitespaceLevel: String,
 
-      _parentIndex: {
-        type: Number,
-        computed: '_computeParentIndex(patchRange.*)',
-      },
+        _parentIndex: {
+          type: Number,
+          computed: '_computeParentIndex(patchRange.*)',
+        },
 
-      _syntaxHighlightingEnabled: {
-        type: Boolean,
-        computed:
+        _syntaxHighlightingEnabled: {
+          type: Boolean,
+          computed:
           '_isSyntaxHighlightingEnabled(prefs.*, diff)',
-      },
+        },
 
-      _layers: {
-        type: Array,
-        value: [],
-      },
-    },
+        _layers: {
+          type: Array,
+          value: [],
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-    ],
-
-    listeners: {
-      // These are named inconsistently for a reason:
-      // The create-comment event is fired to indicate that we should
-      // create a comment.
-      // The comment-* events are just notifying that the comments did already
-      // change in some way, and that we should update any models we may want
-      // to keep in sync.
-      'create-comment': '_handleCreateComment',
-      'comment-discard': '_handleCommentDiscard',
-      'comment-update': '_handleCommentUpdate',
-      'comment-save': '_handleCommentSave',
-
-      'render-start': '_handleRenderStart',
-      'render-content': '_handleRenderContent',
-
-      'normalize-range': '_handleNormalizeRange',
-      'diff-context-expanded': '_handleDiffContextExpanded',
-    },
-
-    observers: [
-      '_whitespaceChanged(prefs.ignore_whitespace, _loadedWhitespaceLevel,' +
+    static get observers() {
+      return [
+        '_whitespaceChanged(prefs.ignore_whitespace, _loadedWhitespaceLevel,' +
           ' noRenderOnPrefsChange)',
-      '_syntaxHighlightingChanged(noRenderOnPrefsChange, prefs.*)',
-    ],
+        '_syntaxHighlightingChanged(noRenderOnPrefsChange, prefs.*)',
+      ];
+    }
+
+    created() {
+      super.created();
+      this.addEventListener(
+          // These are named inconsistently for a reason:
+          // The create-comment event is fired to indicate that we should
+          // create a comment.
+          // The comment-* events are just notifying that the comments did already
+          // change in some way, and that we should update any models we may want
+          // to keep in sync.
+          'create-comment',
+          e => this._handleCreateComment(e));
+      this.addEventListener('comment-discard',
+          e => this._handleCommentDiscard(e));
+      this.addEventListener('comment-update',
+          e => this._handleCommentUpdate(e));
+      this.addEventListener('comment-save',
+          e => this._handleCommentSave(e));
+      this.addEventListener('render-start',
+          () => this._handleRenderStart());
+      this.addEventListener('render-content',
+          () => this._handleRenderContent());
+      this.addEventListener('normalize-range',
+          event => this._handleNormalizeRange(event));
+      this.addEventListener('diff-context-expanded',
+          event => this._handleDiffContextExpanded(event));
+    }
 
     ready() {
+      super.ready();
       if (this._canReload()) {
         this.reload();
       }
-    },
+    }
 
     attached() {
+      super.attached();
       this._getLoggedIn().then(loggedIn => {
         this._loggedIn = loggedIn;
       });
-    },
+    }
 
     /**
      * @param {boolean=} shouldReportMetric indicate a new Diff Page. This is a
@@ -364,7 +381,7 @@
             console.warn('Error encountered loading diff:', err);
           })
           .then(() => { this._loading = false; });
-    },
+    }
 
     _getFilesWeblinks(diff) {
       if (!this.commitRange) {
@@ -378,26 +395,30 @@
             this.projectName, this.commitRange.commit, this.path,
             {weblinks: diff && diff.meta_b && diff.meta_b.web_links}),
       };
-    },
+    }
 
     /** Cancel any remaining diff builder rendering work. */
     cancel() {
       this.$.diff.cancel();
-    },
+    }
 
     /** @return {!Array<!HTMLElement>} */
     getCursorStops() {
       return this.$.diff.getCursorStops();
-    },
+    }
 
     /** @return {boolean} */
     isRangeSelected() {
       return this.$.diff.isRangeSelected();
-    },
+    }
+
+    createRangeComment() {
+      return this.$.diff.createRangeComment();
+    }
 
     toggleLeftDiff() {
       this.$.diff.toggleLeftDiff();
-    },
+    }
 
     /**
      * Load and display blame information for the base of the diff.
@@ -414,12 +435,12 @@
 
             this._blame = blame;
           });
-    },
+    }
 
     /** Unload blame information for the diff. */
     clearBlame() {
       this._blame = null;
-    },
+    }
 
     /**
      * The thread elements in this diff, in no particular order.
@@ -428,31 +449,31 @@
     getThreadEls() {
       return Array.from(
           Polymer.dom(this.$.diff).querySelectorAll('.comment-thread'));
-    },
+    }
 
     /** @param {HTMLElement} el */
     addDraftAtLine(el) {
       this.$.diff.addDraftAtLine(el);
-    },
+    }
 
     clearDiffContent() {
       this.$.diff.clearDiffContent();
-    },
+    }
 
     expandAllContext() {
       this.$.diff.expandAllContext();
-    },
+    }
 
     /** @return {!Promise} */
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     /** @return {boolean}} */
     _canReload() {
       return !!this.changeNum && !!this.patchRange && !!this.path &&
           !this.noAutoRender;
-    },
+    }
 
     /** @return {!Promise<!Object>} */
     _getDiff() {
@@ -468,7 +489,7 @@
             reject)
             .then(resolve);
       });
-    },
+    }
 
     _handleGetDiffError(response) {
       // Loading the diff may respond with 409 if the file is too large. In this
@@ -488,7 +509,7 @@
       }
 
       this.fire('page-error', {response});
-    },
+    }
 
     /**
      * Report info about the diff response.
@@ -529,7 +550,7 @@
         this.$.reporting.reportInteraction(EVENT_NONZERO_REBASE,
             percentRebaseDelta);
       }
-    },
+    }
 
     /**
      * @param {Object} diff
@@ -546,7 +567,7 @@
         this._revisionImage = null;
         return Promise.resolve();
       }
-    },
+    }
 
     /**
      * @param {Object} diff
@@ -554,7 +575,7 @@
      */
     _computeIsImageDiff(diff) {
       return isImageDiff(diff);
-    },
+    }
 
     _commentsChanged(newComments) {
       const allComments = [];
@@ -575,7 +596,7 @@
         const threadEl = this._createThreadElement(thread);
         this._attachThreadElement(threadEl);
       }
-    },
+    }
 
     /**
      * @param {!Array<!Object>} comments
@@ -617,7 +638,7 @@
         threads.push(newThread);
       }
       return threads;
-    },
+    }
 
     /**
      * @param {Object} blame
@@ -625,7 +646,7 @@
      */
     _computeIsBlameLoaded(blame) {
       return !!blame;
-    },
+    }
 
     /**
      * @param {Object} diff
@@ -634,7 +655,7 @@
     _getImages(diff) {
       return this.$.restAPI.getImagesForDiff(this.changeNum, diff,
           this.patchRange);
-    },
+    }
 
     /** @param {CustomEvent} e */
     _handleCreateComment(e) {
@@ -644,7 +665,7 @@
       threadEl.addOrEditDraft(lineNum, range);
 
       this.$.reporting.recordDraftInteraction();
-    },
+    }
 
     /**
      * Gets or creates a comment thread at a given location.
@@ -671,18 +692,18 @@
         this._attachThreadElement(threadEl);
       }
       return threadEl;
-    },
+    }
 
     _attachThreadElement(threadEl) {
       Polymer.dom(this.$.diff).appendChild(threadEl);
-    },
+    }
 
     _clearThreads() {
       for (const threadEl of this.getThreadEls()) {
         const parent = Polymer.dom(threadEl).parentNode;
         Polymer.dom(parent).removeChild(threadEl);
       }
-    },
+    }
 
     _createThreadElement(thread) {
       const threadEl = document.createElement('gr-comment-thread');
@@ -713,7 +734,7 @@
       };
       threadEl.addEventListener('thread-discard', threadDiscardListener);
       return threadEl;
-    },
+    }
 
     /**
      * Gets a comment thread element at a given location.
@@ -742,7 +763,7 @@
       const filteredThreadEls = this._filterThreadElsForLocation(
           this.getThreadEls(), line, commentSide).filter(matchesRange);
       return filteredThreadEls.length ? filteredThreadEls[0] : null;
-    },
+    }
 
     /**
      * @param {!Array<!HTMLElement>} threadEls
@@ -787,14 +808,14 @@
       }
       return threadEls.filter(threadEl =>
         matchers.some(matcher => matcher(threadEl)));
-    },
+    }
 
     _getIgnoreWhitespace() {
       if (!this.prefs || !this.prefs.ignore_whitespace) {
         return WHITESPACE_IGNORE_NONE;
       }
       return this.prefs.ignore_whitespace;
-    },
+    }
 
     _whitespaceChanged(
         preferredWhitespaceLevel, loadedWhitespaceLevel,
@@ -812,7 +833,7 @@
           !noRenderOnPrefsChange) {
         this.reload();
       }
-    },
+    }
 
     _syntaxHighlightingChanged(noRenderOnPrefsChange, prefsChangeRecord) {
       // Polymer 2: check for undefined
@@ -830,7 +851,7 @@
       if (!noRenderOnPrefsChange) {
         this.reload();
       }
-    },
+    }
 
     /**
      * @param {Object} patchRangeRecord
@@ -839,7 +860,7 @@
     _computeParentIndex(patchRangeRecord) {
       return this.isMergeParent(patchRangeRecord.base.basePatchNum) ?
         this.getParentIndex(patchRangeRecord.base.basePatchNum) : null;
-    },
+    }
 
     _handleCommentSave(e) {
       const comment = e.detail.comment;
@@ -847,13 +868,13 @@
       const idx = this._findDraftIndex(comment, side);
       this.set(['comments', side, idx], comment);
       this._handleCommentSaveOrDiscard();
-    },
+    }
 
     _handleCommentDiscard(e) {
       const comment = e.detail.comment;
       this._removeComment(comment);
       this._handleCommentSaveOrDiscard();
-    },
+    }
 
     /**
      * Closure annotation for Polymer.prototype.push is off. Submitted PR:
@@ -874,17 +895,17 @@
       } else { // Create new draft.
         this.push(['comments', side], comment);
       }
-    },
+    }
 
     _handleCommentSaveOrDiscard() {
       this.dispatchEvent(new CustomEvent(
           'diff-comments-modified', {bubbles: true, composed: true}));
-    },
+    }
 
     _removeComment(comment) {
       const side = comment.__commentSide;
       this._removeCommentFromSide(comment, side);
-    },
+    }
 
     _removeCommentFromSide(comment, side) {
       let idx = this._findCommentIndex(comment, side);
@@ -894,7 +915,7 @@
       if (idx !== -1) {
         this.splice('comments.' + side, idx, 1);
       }
-    },
+    }
 
     /** @return {number} */
     _findCommentIndex(comment, side) {
@@ -902,7 +923,7 @@
         return -1;
       }
       return this.comments[side].findIndex(item => item.id === comment.id);
-    },
+    }
 
     /** @return {number} */
     _findDraftIndex(comment, side) {
@@ -911,7 +932,7 @@
       }
       return this.comments[side].findIndex(
           item => item.__draftID === comment.__draftID);
-    },
+    }
 
     _isSyntaxHighlightingEnabled(preferenceChangeRecord, diff) {
       if (!preferenceChangeRecord ||
@@ -922,7 +943,7 @@
       }
       return !this._anyLineTooLong(diff) &&
           this.$.diff.getDiffLength(diff) <= SYNTAX_MAX_DIFF_LENGTH;
-    },
+    }
 
     /**
      * @return {boolean} whether any of the lines in diff are longer
@@ -936,7 +957,7 @@
           (section.a || []).concat(section.b || []);
         return lines.some(line => line.length >= SYNTAX_MAX_LINE_LENGTH);
       });
-    },
+    }
 
     _listenToViewportRender() {
       const renderUpdateListener = start => {
@@ -947,26 +968,28 @@
       };
 
       this.$.syntaxLayer.addListener(renderUpdateListener);
-    },
+    }
 
     _handleRenderStart() {
       this.$.reporting.time(TimingLabel.TOTAL);
       this.$.reporting.time(TimingLabel.CONTENT);
-    },
+    }
 
     _handleRenderContent() {
       this.$.reporting.timeEnd(TimingLabel.CONTENT);
-    },
+    }
 
     _handleNormalizeRange(event) {
       this.$.reporting.reportInteraction('normalize-range',
           `Modified invalid comment range on l. ${event.detail.lineNum}` +
           ` of the ${event.detail.side} side`);
-    },
+    }
 
     _handleDiffContextExpanded(event) {
       this.$.reporting.reportInteraction(
           'diff-context-expanded', event.detail.numLines);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffHost.is, GrDiffHost);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
index eb0a68d..ea94441 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.html b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.html
index bf3fbc9..47cf771 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.html
@@ -16,6 +16,7 @@
 -->
 
 <link rel="import" href="/bower_components/polymer/polymer.html">
+<link rel="import" href="/bower_components/iron-icon/iron-icon.html">
 <link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.js b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.js
index 88dd91a..8d8785a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector.js
@@ -17,34 +17,38 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-diff-mode-selector',
+  class GrDiffModeSelector extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-diff-mode-selector'; }
 
-    properties: {
-      mode: {
-        type: String,
-        notify: true,
-      },
+    static get properties() {
+      return {
+        mode: {
+          type: String,
+          notify: true,
+        },
 
-      /**
+        /**
        * If set to true, the user's preference will be updated every time a
        * button is tapped. Don't set to true if there is no user.
        */
-      saveOnChange: {
-        type: Boolean,
-        value: false,
-      },
-
-      /** @type {?} */
-      _VIEW_MODES: {
-        type: Object,
-        readOnly: true,
-        value: {
-          SIDE_BY_SIDE: 'SIDE_BY_SIDE',
-          UNIFIED: 'UNIFIED_DIFF',
+        saveOnChange: {
+          type: Boolean,
+          value: false,
         },
-      },
-    },
+
+        /** @type {?} */
+        _VIEW_MODES: {
+          type: Object,
+          readOnly: true,
+          value: {
+            SIDE_BY_SIDE: 'SIDE_BY_SIDE',
+            UNIFIED: 'UNIFIED_DIFF',
+          },
+        },
+      };
+    }
 
     /**
      * Set the mode. If save on change is enabled also update the preference.
@@ -54,18 +58,20 @@
         this.$.restAPI.savePreferences({diff_view: newMode});
       }
       this.mode = newMode;
-    },
+    }
 
     _computeSelectedClass(diffViewMode, buttonViewMode) {
       return buttonViewMode === diffViewMode ? 'selected' : '';
-    },
+    }
 
     _handleSideBySideTap() {
       this.setMode(this._VIEW_MODES.SIDE_BY_SIDE);
-    },
+    }
 
     _handleUnifiedTap() {
       this.setMode(this._VIEW_MODES.UNIFIED);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffModeSelector.is, GrDiffModeSelector);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html
index adeaa15..333a3d6 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-mode-selector/gr-diff-mode-selector_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-mode-selector</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.js b/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.js
index 6ecd4d6..2d79311 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.js
@@ -17,39 +17,44 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-diff-preferences-dialog',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrDiffPreferencesDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff-preferences-dialog'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      diffPrefs: Object,
+        diffPrefs: Object,
 
-      _diffPrefsChanged: Boolean,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+        _diffPrefsChanged: Boolean,
+      };
+    }
 
     getFocusStops() {
       return {
         start: this.$.diffPreferences.$.contextSelect,
         end: this.$.saveButton,
       };
-    },
+    }
 
     resetFocus() {
       this.$.diffPreferences.$.contextSelect.focus();
-    },
+    }
 
     _computeHeaderClass(changed) {
       return changed ? 'edited' : '';
-    },
+    }
 
     _handleCancelDiff(e) {
       e.stopPropagation();
       this.$.diffPrefsOverlay.close();
-    },
+    }
 
     open() {
       this.$.diffPrefsOverlay.open().then(() => {
@@ -57,7 +62,7 @@
         this.$.diffPrefsOverlay.setFocusStops(focusStops);
         this.resetFocus();
       });
-    },
+    }
 
     _handleSaveDiffPreferences() {
       this.$.diffPreferences.save().then(() => {
@@ -65,6 +70,8 @@
 
         this.$.diffPrefsOverlay.close();
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffPreferencesDialog.is, GrDiffPreferencesDialog);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
index b67bde3..817da45 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor.js
@@ -64,71 +64,77 @@
    *    that the part that is within the context or has comments is shown, while
    *    the rest is not.
    */
-  Polymer({
-    is: 'gr-diff-processor',
+  class GrDiffProcessor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-diff-processor'; }
 
-    properties: {
+    static get properties() {
+      return {
 
-      /**
+        /**
        * The amount of context around collapsed groups.
        */
-      context: Number,
+        context: Number,
 
-      /**
+        /**
        * The array of groups output by the processor.
        */
-      groups: {
-        type: Array,
-        notify: true,
-      },
+        groups: {
+          type: Array,
+          notify: true,
+        },
 
-      /**
+        /**
        * Locations that should not be collapsed, including the locations of
        * comments.
        */
-      keyLocations: {
-        type: Object,
-        value() { return {left: {}, right: {}}; },
-      },
+        keyLocations: {
+          type: Object,
+          value() { return {left: {}, right: {}}; },
+        },
 
-      /**
+        /**
        * The maximum number of lines to process synchronously.
        */
-      _asyncThreshold: {
-        type: Number,
-        value: 64,
-      },
+        _asyncThreshold: {
+          type: Number,
+          value: 64,
+        },
 
-      /** @type {?number} */
-      _nextStepHandle: Number,
-      /**
+        /** @type {?number} */
+        _nextStepHandle: Number,
+        /**
        * The promise last returned from `process()` while the asynchronous
        * processing is running - `null` otherwise. Provides a `cancel()`
        * method that rejects it with `{isCancelled: true}`.
        * @type {?Object}
        */
-      _processPromise: {
-        type: Object,
-        value: null,
-      },
-      _isScrolling: Boolean,
-    },
+        _processPromise: {
+          type: Object,
+          value: null,
+        },
+        _isScrolling: Boolean,
+      };
+    }
 
     attached() {
+      super.attached();
       this.listen(window, 'scroll', '_handleWindowScroll');
-    },
+    }
 
     detached() {
+      super.detached();
       this.cancel();
       this.unlisten(window, 'scroll', '_handleWindowScroll');
-    },
+    }
 
     _handleWindowScroll() {
       this._isScrolling = true;
       this.debounce('resetIsScrolling', () => {
         this._isScrolling = false;
       }, 50);
-    },
+    }
 
     /**
      * Asynchronously process the diff chunks into groups. As it processes, it
@@ -196,7 +202,7 @@
           }));
       return this._processPromise
           .finally(() => { this._processPromise = null; });
-    },
+    }
 
     /**
      * Cancel any jobs that are running.
@@ -209,7 +215,7 @@
       if (this._processPromise) {
         this._processPromise.cancel();
       }
-    },
+    }
 
     /**
      * Process the next uncollapsible chunk, or the next collapsible chunks.
@@ -236,15 +242,15 @@
 
       return this._processCollapsibleChunks(
           state, chunks, firstUncollapsibleChunkIndex);
-    },
+    }
 
     _linesLeft(chunk) {
       return chunk.ab || chunk.a || [];
-    },
+    }
 
     _linesRight(chunk) {
       return chunk.ab || chunk.b || [];
-    },
+    }
 
     _firstUncollapsibleChunkIndex(chunks, offset) {
       let chunkIndex = offset;
@@ -253,11 +259,11 @@
         chunkIndex++;
       }
       return chunkIndex;
-    },
+    }
 
     _isCollapsibleChunk(chunk) {
       return (chunk.ab || chunk.common) && !chunk.keyLocation;
-    },
+    }
 
     /**
      * Process a stretch of collapsible chunks.
@@ -303,7 +309,7 @@
         groups,
         newChunkIndex: firstUncollapsibleChunkIndex,
       };
-    },
+    }
 
     _commonChunkLength(chunk) {
       console.assert(chunk.ab || chunk.common);
@@ -311,7 +317,7 @@
           !chunk.a || (chunk.b && chunk.a.length === chunk.b.length),
           `common chunk needs same number of a and b lines: `, chunk);
       return this._linesLeft(chunk).length;
-    },
+    }
 
     /**
      * @param {!Array<!Object>} chunks
@@ -327,7 +333,7 @@
         offsetRight += chunkLength;
         return group;
       });
-    },
+    }
 
     /**
      * @param {!Object} chunk
@@ -343,7 +349,7 @@
       group.dueToRebase = chunk.due_to_rebase;
       group.ignoredWhitespaceOnly = chunk.common;
       return group;
-    },
+    }
 
     _linesFromChunk(chunk, offsetLeft, offsetRight) {
       if (chunk.ab) {
@@ -366,7 +372,7 @@
             chunk[DiffHighlights.ADDED]));
       }
       return lines;
-    },
+    }
 
     /**
      * @param {string} lineType (GrDiffLine.Type)
@@ -380,7 +386,7 @@
         this._convertIntralineInfos(rows, opt_intralineInfos) : undefined;
       return rows.map((row, i) => this._lineFromRow(
           lineType, offset, offset, row, i, grDiffHighlights));
-    },
+    }
 
     /**
      * @param {string} type (GrDiffLine.Type)
@@ -403,14 +409,14 @@
         line.hasIntralineInfo = false;
       }
       return line;
-    },
+    }
 
     _makeFileComments() {
       const line = new GrDiffLine(GrDiffLine.Type.BOTH);
       line.beforeNumber = GrDiffLine.FILE;
       line.afterNumber = GrDiffLine.FILE;
       return new GrDiffGroup(GrDiffGroup.Type.BOTH, [line]);
-    },
+    }
 
     /**
      * Split chunks into smaller chunks of the same kind.
@@ -452,7 +458,7 @@
         }
       }
       return newChunks;
-    },
+    }
 
     /**
      * In order to show key locations, such as comments, out of the bounds of
@@ -503,7 +509,7 @@
       }
 
       return result;
-    },
+    }
 
     /**
      * @return {!Array<{offset: number, keyLocation: boolean}>} Offsets of the
@@ -534,7 +540,7 @@
       }
 
       return result;
-    },
+    }
 
     _splitAtChunkEnds(lines, chunkEnds) {
       const result = [];
@@ -545,7 +551,7 @@
         lastChunkEndOffset = offset;
       }
       return result;
-    },
+    }
 
     /**
      * Converts `IntralineInfo`s return by the API to `GrLineHighlights` used
@@ -595,7 +601,7 @@
         normalized.push(lineHighlight);
       }
       return normalized;
-    },
+    }
 
     /**
      * If a group is an addition or a removal, break it down into smaller groups
@@ -625,7 +631,7 @@
             }
             return subChunk;
           });
-    },
+    }
 
     /**
      * Given an array and a size, return an array of arrays where no inner array
@@ -643,6 +649,8 @@
       const tail = array.slice(array.length - size);
 
       return this._breakdown(head, size).concat([tail]);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffProcessor.is, GrDiffProcessor);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
index c04b066..308428f 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-processor/gr-diff-processor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-processor test</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
index c35c304..0dc0fba 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.js
@@ -30,35 +30,46 @@
 
   const getNewCache = () => { return {left: null, right: null}; };
 
-  Polymer({
-    is: 'gr-diff-selection',
+  /**
+    * @appliesMixin Gerrit.DomUtilMixin
+    */
+  class GrDiffSelection extends Polymer.mixinBehaviors( [
+    Gerrit.DomUtilBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff-selection'; }
 
-    properties: {
-      diff: Object,
-      /** @type {?Object} */
-      _cachedDiffBuilder: Object,
-      _linesCache: {
-        type: Object,
-        value: getNewCache(),
-      },
-    },
+    static get properties() {
+      return {
+        diff: Object,
+        /** @type {?Object} */
+        _cachedDiffBuilder: Object,
+        _linesCache: {
+          type: Object,
+          value: getNewCache(),
+        },
+      };
+    }
 
-    observers: [
-      '_diffChanged(diff)',
-    ],
+    static get observers() {
+      return [
+        '_diffChanged(diff)',
+      ];
+    }
 
-    listeners: {
-      copy: '_handleCopy',
-      down: '_handleDown',
-    },
-
-    behaviors: [
-      Gerrit.DomUtilBehavior,
-    ],
+    created() {
+      super.created();
+      this.addEventListener('copy',
+          e => this._handleCopy(e));
+      Polymer.Gestures.addListener(this, 'down',
+          e => this._handleDown(e));
+    }
 
     attached() {
+      super.attached();
       this.classList.add(SelectionClass.RIGHT);
-    },
+    }
 
     get diffBuilder() {
       if (!this._cachedDiffBuilder) {
@@ -66,11 +77,11 @@
             Polymer.dom(this).querySelector('gr-diff-builder');
       }
       return this._cachedDiffBuilder;
-    },
+    }
 
     _diffChanged() {
       this._linesCache = getNewCache();
-    },
+    }
 
     _handleDownOnRangeComment(node) {
       if (node &&
@@ -85,7 +96,7 @@
         return true;
       }
       return false;
-    },
+    }
 
     _handleDown(e) {
       // Handle the down event on comment thread in Polymer 2
@@ -115,7 +126,7 @@
       }
 
       this._setClasses(targetClasses);
-    },
+    }
 
     /**
      * Set the provided list of classes on the element, to the exclusion of all
@@ -138,11 +149,11 @@
           this.classList.add(_class);
         }
       }
-    },
+    }
 
     _getCopyEventTarget(e) {
       return Polymer.dom(e).rootTarget;
-    },
+    }
 
     /**
      * Utility function to determine whether an element is a descendant of
@@ -155,7 +166,7 @@
     _elementDescendedFromClass(element, className) {
       return this.descendedFromClass(element, className,
           this.diffBuilder.diffElement);
-    },
+    }
 
     _handleCopy(e) {
       let commentSelected = false;
@@ -175,7 +186,7 @@
         e.clipboardData.setData('Text', text);
         e.preventDefault();
       }
-    },
+    }
 
     /**
      * For Polymer 2, use shadowRoot.getSelection instead.
@@ -186,7 +197,7 @@
         diffHost.shadowRoot &&
         diffHost.shadowRoot.getSelection();
       return selection ? selection: window.getSelection();
-    },
+    }
 
     /**
      * Get the text of the current selection. If commentSelected is
@@ -225,7 +236,7 @@
 
       return this._getRangeFromDiff(startLineNum, range.startOffset, endLineNum,
           range.endOffset, side);
-    },
+    }
 
     /**
      * Query the diff object for the selected lines.
@@ -247,7 +258,7 @@
         lines[0] = lines[0].substring(startOffset);
       }
       return lines.join('\n');
-    },
+    }
 
     /**
      * Query the diff object for the lines from a particular side.
@@ -270,7 +281,7 @@
       }
       this._linesCache[side] = lines;
       return lines;
-    },
+    }
 
     /**
      * Query the diffElement for comments and check whether they lie inside the
@@ -308,7 +319,7 @@
       }
 
       return content.join('\n');
-    },
+    }
 
     /**
      * Given a DOM node, a selection, and a selection range, recursively get all
@@ -338,6 +349,8 @@
         }
       }
       return text;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffSelection.is, GrDiffSelection);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
index 9385658..6fe319d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-selection</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index a3ddaf7..4c401cf 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -33,9 +33,23 @@
     UNIFIED: 'UNIFIED_DIFF',
   };
 
-  Polymer({
-    is: 'gr-diff-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.PathListMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrDiffView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.PathListBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff-view'; }
     /**
      * Fired when the title of the page should change.
      *
@@ -48,154 +62,152 @@
      * @event show-alert
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      /**
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        /**
        * @type {{ diffMode: (string|undefined) }}
        */
-      changeViewState: {
-        type: Object,
-        notify: true,
-        value() { return {}; },
-        observer: '_changeViewStateChanged',
-      },
-      disableDiffPrefs: {
-        type: Boolean,
-        value: false,
-      },
-      _diffPrefsDisabled: {
-        type: Boolean,
-        computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
-      },
-      /** @type {?} */
-      _patchRange: Object,
-      /** @type {?} */
-      _commitRange: Object,
-      /**
+        changeViewState: {
+          type: Object,
+          notify: true,
+          value() { return {}; },
+          observer: '_changeViewStateChanged',
+        },
+        disableDiffPrefs: {
+          type: Boolean,
+          value: false,
+        },
+        _diffPrefsDisabled: {
+          type: Boolean,
+          computed: '_computeDiffPrefsDisabled(disableDiffPrefs, _loggedIn)',
+        },
+        /** @type {?} */
+        _patchRange: Object,
+        /** @type {?} */
+        _commitRange: Object,
+        /**
        * @type {{
        *  subject: string,
        *  project: string,
        *  revisions: string,
        * }}
        */
-      _change: Object,
-      /** @type {?} */
-      _changeComments: Object,
-      _changeNum: String,
-      /**
+        _change: Object,
+        /** @type {?} */
+        _changeComments: Object,
+        _changeNum: String,
+        /**
        * This is a DiffInfo object.
        * This is retrieved and owned by a child component.
        */
-      _diff: Object,
-      // An array specifically formatted to be used in a gr-dropdown-list
-      // element for selected a file to view.
-      _formattedFiles: {
-        type: Array,
-        computed: '_formatFilesForDropdown(_fileList, _patchRange.patchNum, ' +
-            '_changeComments)',
-      },
-      // An sorted array of files, as returned by the rest API.
-      _fileList: {
-        type: Array,
-        value() { return []; },
-      },
-      _path: {
-        type: String,
-        observer: '_pathChanged',
-      },
-      _fileNum: {
-        type: Number,
-        computed: '_computeFileNum(_path, _formattedFiles)',
-      },
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _prefs: Object,
-      _localPrefs: Object,
-      _projectConfig: Object,
-      _userPrefs: Object,
-      _diffMode: {
-        type: String,
-        computed: '_getDiffViewMode(changeViewState.diffMode, _userPrefs)',
-      },
-      _isImageDiff: Boolean,
-      _filesWeblinks: Object,
+        _diff: Object,
+        // An array specifically formatted to be used in a gr-dropdown-list
+        // element for selected a file to view.
+        _formattedFiles: {
+          type: Array,
+          computed: '_formatFilesForDropdown(_fileList, ' +
+            '_patchRange.patchNum, _changeComments)',
+        },
+        // An sorted array of files, as returned by the rest API.
+        _fileList: {
+          type: Array,
+          value() { return []; },
+        },
+        _path: {
+          type: String,
+          observer: '_pathChanged',
+        },
+        _fileNum: {
+          type: Number,
+          computed: '_computeFileNum(_path, _formattedFiles)',
+        },
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _prefs: Object,
+        _localPrefs: Object,
+        _projectConfig: Object,
+        _userPrefs: Object,
+        _diffMode: {
+          type: String,
+          computed: '_getDiffViewMode(changeViewState.diffMode, _userPrefs)',
+        },
+        _isImageDiff: Boolean,
+        _filesWeblinks: Object,
 
-      /**
+        /**
        * Map of paths in the current change and patch range that have comments
        * or drafts or robot comments.
        */
-      _commentMap: Object,
+        _commentMap: Object,
 
-      _commentsForDiff: Object,
+        _commentsForDiff: Object,
 
-      /**
+        /**
        * Object to contain the path of the next and previous file in the current
        * change and patch range that has comments.
        */
-      _commentSkips: {
-        type: Object,
-        computed: '_computeCommentSkips(_commentMap, _fileList, _path)',
-      },
-      _panelFloatingDisabled: {
-        type: Boolean,
-        value: () => { return window.PANEL_FLOATING_DISABLED; },
-      },
-      _editMode: {
-        type: Boolean,
-        computed: '_computeEditMode(_patchRange.*)',
-      },
-      _isBlameLoaded: Boolean,
-      _isBlameLoading: {
-        type: Boolean,
-        value: false,
-      },
-      _allPatchSets: {
-        type: Array,
-        computed: 'computeAllPatchSets(_change, _change.revisions.*)',
-      },
-      _revisionInfo: {
-        type: Object,
-        computed: '_getRevisionInfo(_change)',
-      },
-      _reviewedFiles: {
-        type: Object,
-        value: () => new Set(),
-      },
-    },
+        _commentSkips: {
+          type: Object,
+          computed: '_computeCommentSkips(_commentMap, _fileList, _path)',
+        },
+        _panelFloatingDisabled: {
+          type: Boolean,
+          value: () => { return window.PANEL_FLOATING_DISABLED; },
+        },
+        _editMode: {
+          type: Boolean,
+          computed: '_computeEditMode(_patchRange.*)',
+        },
+        _isBlameLoaded: Boolean,
+        _isBlameLoading: {
+          type: Boolean,
+          value: false,
+        },
+        _allPatchSets: {
+          type: Array,
+          computed: 'computeAllPatchSets(_change, _change.revisions.*)',
+        },
+        _revisionInfo: {
+          type: Object,
+          computed: '_getRevisionInfo(_change)',
+        },
+        _reviewedFiles: {
+          type: Object,
+          value: () => new Set(),
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.PathListBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
+    static get observers() {
+      return [
+        '_getProjectConfig(_change.project)',
+        '_getFiles(_changeNum, _patchRange.*)',
+        '_setReviewedObserver(_loggedIn, params.*, _prefs)',
+      ];
+    }
 
-    observers: [
-      '_getProjectConfig(_change.project)',
-      '_getFiles(_changeNum, _patchRange.*)',
-      '_setReviewedObserver(_loggedIn, params.*, _prefs)',
-    ],
-
-    keyBindings: {
-      esc: '_handleEscKey',
-    },
+    get keyBindings() {
+      return {
+        esc: '_handleEscKey',
+      };
+    }
 
     keyboardShortcuts() {
       return {
@@ -230,37 +242,38 @@
         [this.Shortcut.EXPAND_ALL_COMMENT_THREADS]: null,
         [this.Shortcut.COLLAPSE_ALL_COMMENT_THREADS]: null,
       };
-    },
+    }
 
     attached() {
+      super.attached();
       this._getLoggedIn().then(loggedIn => {
         this._loggedIn = loggedIn;
       });
 
       this.$.cursor.push('diffs', this.$.diffHost);
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getProjectConfig(project) {
       return this.$.restAPI.getProjectConfig(project).then(
           config => {
             this._projectConfig = config;
           });
-    },
+    }
 
     _getChangeDetail(changeNum) {
       return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
         this._change = change;
         return change;
       });
-    },
+    }
 
     _getChangeEdit(changeNum) {
       return this.$.restAPI.getChangeEdit(this._changeNum);
-    },
+    }
 
     _getFiles(changeNum, patchRangeRecord) {
       // Polymer 2: check for undefined
@@ -274,25 +287,25 @@
           changeNum, patchRange).then(files => {
         this._fileList = files;
       });
-    },
+    }
 
     _getDiffPreferences() {
       return this.$.restAPI.getDiffPreferences().then(prefs => {
         this._prefs = prefs;
       });
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     _getWindowWidth() {
       return window.innerWidth;
-    },
+    }
 
     _handleReviewedChange(e) {
       this._setReviewed(Polymer.dom(e).rootTarget.checked);
-    },
+    }
 
     _setReviewed(reviewed) {
       if (this._editMode) { return; }
@@ -301,12 +314,12 @@
         this.fire('show-alert', {message: ERR_REVIEW_STATUS});
         throw err;
       });
-    },
+    }
 
     _saveReviewedState(reviewed) {
       return this.$.restAPI.saveFileReviewed(this._changeNum,
           this._patchRange.patchNum, this._path, reviewed);
-    },
+    }
 
     _handleToggleFileReviewed(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -314,7 +327,7 @@
 
       e.preventDefault();
       this._setReviewed(!this.$.reviewed.checked);
-    },
+    }
 
     _handleEscKey(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -322,21 +335,21 @@
 
       e.preventDefault();
       this.$.diffHost.displayLine = false;
-    },
+    }
 
     _handleLeftPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       e.preventDefault();
       this.$.cursor.moveLeft();
-    },
+    }
 
     _handleRightPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       e.preventDefault();
       this.$.cursor.moveRight();
-    },
+    }
 
     _handlePrevLineOrFileWithComments(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -350,7 +363,7 @@
       e.preventDefault();
       this.$.diffHost.displayLine = true;
       this.$.cursor.moveUp();
-    },
+    }
 
     _handleNextLineOrFileWithComments(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -364,7 +377,7 @@
       e.preventDefault();
       this.$.diffHost.displayLine = true;
       this.$.cursor.moveDown();
-    },
+    }
 
     _moveToPreviousFileWithComment() {
       if (!this._commentSkips) { return; }
@@ -378,7 +391,7 @@
 
       Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.previous,
           this._patchRange.patchNum, this._patchRange.basePatchNum);
-    },
+    }
 
     _moveToNextFileWithComment() {
       if (!this._commentSkips) { return; }
@@ -391,19 +404,14 @@
 
       Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.next,
           this._patchRange.patchNum, this._patchRange.basePatchNum);
-    },
+    }
 
     _handleNewComment(e) {
-      if (this.shouldSuppressKeyboardShortcut(e)) { return; }
-      if (this.$.diffHost.isRangeSelected()) { return; }
-      if (this.modifierPressed(e)) { return; }
-
+      if (this.shouldSuppressKeyboardShortcut(e) ||
+          this.modifierPressed(e)) { return; }
       e.preventDefault();
-      const line = this.$.cursor.getTargetLineElement();
-      if (line) {
-        this.$.diffHost.addDraftAtLine(line);
-      }
-    },
+      this.$.cursor.createCommentInPlace();
+    }
 
     _handlePrevFile(e) {
       // Check for meta key to avoid overriding native chrome shortcut.
@@ -412,7 +420,7 @@
 
       e.preventDefault();
       this._navToFile(this._path, this._fileList, -1);
-    },
+    }
 
     _handleNextFile(e) {
       // Check for meta key to avoid overriding native chrome shortcut.
@@ -421,7 +429,7 @@
 
       e.preventDefault();
       this._navToFile(this._path, this._fileList, 1);
-    },
+    }
 
     _handleNextChunkOrCommentThread(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -433,7 +441,7 @@
         if (this.modifierPressed(e)) { return; }
         this.$.cursor.moveToNextChunk();
       }
-    },
+    }
 
     _handlePrevChunkOrCommentThread(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -445,7 +453,7 @@
         if (this.modifierPressed(e)) { return; }
         this.$.cursor.moveToPreviousChunk();
       }
-    },
+    }
 
     _handleOpenReplyDialogOrToggleLeftPane(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -463,7 +471,7 @@
       this.set('changeViewState.showReplyDialog', true);
       e.preventDefault();
       this._navToChangeView();
-    },
+    }
 
     _handleUpToChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -471,7 +479,7 @@
 
       e.preventDefault();
       this._navToChangeView();
-    },
+    }
 
     _handleCommaKey(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -480,7 +488,7 @@
 
       e.preventDefault();
       this.$.diffPreferencesDialog.open();
-    },
+    }
 
     _handleToggleDiffMode(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -492,7 +500,7 @@
       } else {
         this.$.modeSelect.setMode(DiffViewMode.SIDE_BY_SIDE);
       }
-    },
+    }
 
     _navToChangeView() {
       if (!this._changeNum || !this._patchRange.patchNum) { return; }
@@ -500,7 +508,7 @@
           this._change,
           this._patchRange,
           this._change && this._change.revisions);
-    },
+    }
 
     _navToFile(path, fileList, direction) {
       const newPath = this._getNavLinkPath(path, fileList, direction);
@@ -516,7 +524,7 @@
 
       Gerrit.Nav.navigateToDiff(this._change, newPath.path,
           this._patchRange.patchNum, this._patchRange.basePatchNum);
-    },
+    }
 
     /**
      * @param {?string} path The path of the current file being shown.
@@ -540,7 +548,7 @@
             this._change && this._change.revisions);
       }
       return this._getDiffUrl(this._change, this._patchRange, newPath.path);
-    },
+    }
 
     /**
      * Gives an object representing the target of navigating either left or
@@ -580,7 +588,7 @@
       }
 
       return {path: fileList[idx]};
-    },
+    }
 
     _getReviewedFiles(changeNum, patchNum) {
       return this.$.restAPI.getReviewedFiles(changeNum, patchNum)
@@ -588,13 +596,13 @@
             this._reviewedFiles = new Set(files);
             return this._reviewedFiles;
           });
-    },
+    }
 
     _getReviewedStatus(editMode, changeNum, patchNum, path) {
       if (editMode) { return Promise.resolve(false); }
       return this._getReviewedFiles(changeNum, patchNum)
           .then(files => files.has(path));
-    },
+    }
 
     _paramsChanged(value) {
       if (value.view !== Gerrit.Nav.View.DIFF) { return; }
@@ -681,7 +689,7 @@
         // If diff view displayed has not ended yet, it ends here.
         this.$.reporting.diffViewDisplayed();
       });
-    },
+    }
 
     _changeViewStateChanged(changeViewState) {
       if (changeViewState.diffMode === null) {
@@ -690,7 +698,7 @@
           this.set('changeViewState.diffMode', prefs.default_diff_view);
         });
       }
-    },
+    }
 
     _setReviewedObserver(_loggedIn, paramsRecord, _prefs) {
       // Polymer 2: check for undefined
@@ -714,7 +722,7 @@
       if (params.view === Gerrit.Nav.View.DIFF) {
         this._setReviewed(true);
       }
-    },
+    }
 
     /**
      * If the params specify a diff address then configure the diff cursor.
@@ -727,14 +735,14 @@
         this.$.cursor.side = DiffSides.RIGHT;
       }
       this.$.cursor.initialLineNumber = params.lineNum;
-    },
+    }
 
     _getLineOfInterest(params) {
       // If there is a line number specified, pass it along to the diff so that
       // it will not get collapsed.
       if (!params.lineNum) { return null; }
       return {number: params.lineNum, leftSide: params.leftSide};
-    },
+    }
 
     _pathChanged(path) {
       if (path) {
@@ -746,7 +754,7 @@
 
       this.set('changeViewState.selectedFileIndex',
           this._fileList.indexOf(path));
-    },
+    }
 
     _getDiffUrl(change, patchRange, path) {
       if ([change, patchRange, path].some(arg => arg === undefined)) {
@@ -754,7 +762,7 @@
       }
       return Gerrit.Nav.getUrlForDiff(change, path, patchRange.patchNum,
           patchRange.basePatchNum);
-    },
+    }
 
     _patchRangeStr(patchRange) {
       let patchStr = patchRange.patchNum;
@@ -763,7 +771,7 @@
         patchStr = patchRange.basePatchNum + '..' + patchRange.patchNum;
       }
       return patchStr;
-    },
+    }
 
     /**
      * When the latest patch of the change is selected (and there is no base
@@ -787,7 +795,7 @@
         basePatchNum = patchRange.basePatchNum;
       }
       return {patchNum, basePatchNum};
-    },
+    }
 
     _getChangePath(change, patchRange, revisions) {
       if ([change, patchRange].some(arg => arg === undefined)) {
@@ -796,16 +804,16 @@
       const range = this._getChangeUrlRange(patchRange, revisions);
       return Gerrit.Nav.getUrlForChange(change, range.patchNum,
           range.basePatchNum);
-    },
+    }
 
     _navigateToChange(change, patchRange, revisions) {
       const range = this._getChangeUrlRange(patchRange, revisions);
       Gerrit.Nav.navigateToChange(change, range.patchNum, range.basePatchNum);
-    },
+    }
 
     _computeChangePath(change, patchRangeRecord, revisions) {
       return this._getChangePath(change, patchRangeRecord.base, revisions);
-    },
+    }
 
     _formatFilesForDropdown(fileList, patchNum, changeComments) {
       // Polymer 2: check for undefined
@@ -829,7 +837,7 @@
         });
       }
       return dropdownContent;
-    },
+    }
 
     _computeCommentString(changeComments, patchNum, path) {
       const unresolvedCount = changeComments.computeUnresolvedNum(patchNum,
@@ -845,11 +853,11 @@
           (commentString && unresolvedString ? ', ' : '') +
           // Add parentheses around unresolved if it exists.
           (unresolvedString ? `${unresolvedString}` : '');
-    },
+    }
 
     _computePrefsButtonHidden(prefs, prefsDisabled) {
       return prefsDisabled || !prefs;
-    },
+    }
 
     _handleFileChange(e) {
       // This is when it gets set initially.
@@ -860,7 +868,7 @@
 
       Gerrit.Nav.navigateToDiff(this._change, path, this._patchRange.patchNum,
           this._patchRange.basePatchNum);
-    },
+    }
 
     _handleFileTap(e) {
       // async is needed so that that the click event is fired before the
@@ -868,7 +876,7 @@
       this.async(() => {
         this.$.dropdown.close();
       }, 1);
-    },
+    }
 
     _handlePatchChange(e) {
       const {basePatchNum, patchNum} = e.detail;
@@ -876,12 +884,12 @@
           this.patchNumEquals(patchNum, this._patchRange.patchNum)) { return; }
       Gerrit.Nav.navigateToDiff(
           this._change, this._path, patchNum, basePatchNum);
-    },
+    }
 
     _handlePrefsTap(e) {
       e.preventDefault();
       this.$.diffPreferencesDialog.open();
-    },
+    }
 
     /**
      * _getDiffViewMode: Get the diff view (side-by-side or unified) based on
@@ -906,11 +914,11 @@
       } else {
         return 'SIDE_BY_SIDE';
       }
-    },
+    }
 
     _computeModeSelectHideClass(isImageDiff) {
       return isImageDiff ? 'hide' : '';
-    },
+    }
 
     _onLineSelected(e, detail) {
       this.$.cursor.moveToLineNumber(detail.number, detail.side);
@@ -922,7 +930,7 @@
           this._change.project, this._path, this._patchRange.patchNum,
           this._patchRange.basePatchNum, number, leftSide);
       history.replaceState(null, '', url);
-    },
+    }
 
     _computeDownloadDropdownLinks(
         project, changeNum, patchRange, path, diff) {
@@ -961,7 +969,7 @@
       }
 
       return links;
-    },
+    }
 
     _computeDownloadFileLink(
         project, changeNum, patchRange, path, isBase) {
@@ -981,13 +989,13 @@
       }
 
       return url;
-    },
+    }
 
     _computeDownloadPatchLink(project, changeNum, patchRange, path) {
       let url = this.changeBaseURL(project, changeNum, patchRange.patchNum);
       url += '/patch?zip&path=' + encodeURIComponent(path);
       return url;
-    },
+    }
 
     _loadComments() {
       return this.$.commentAPI.loadAll(this._changeNum).then(comments => {
@@ -997,20 +1005,20 @@
         this._commentsForDiff = this._getCommentsForPath(this._path,
             this._patchRange, this._projectConfig);
       });
-    },
+    }
 
     _getPaths(patchRange) {
       return this._changeComments.getPaths(patchRange);
-    },
+    }
 
     _getCommentsForPath(path, patchRange, projectConfig) {
       return this._changeComments.getCommentsBySideForPath(path, patchRange,
           projectConfig);
-    },
+    }
 
     _getDiffDrafts() {
       return this.$.restAPI.getDiffDrafts(this._changeNum);
-    },
+    }
 
     _computeCommentSkips(commentMap, fileList, path) {
       // Polymer 2: check for undefined
@@ -1043,13 +1051,13 @@
       }
 
       return skips;
-    },
+    }
 
     _computeDiffClass(panelFloatingDisabled) {
       if (panelFloatingDisabled) {
         return 'noOverflow';
       }
-    },
+    }
 
     /**
      * @param {!Object} patchRangeRecord
@@ -1057,19 +1065,19 @@
     _computeEditMode(patchRangeRecord) {
       const patchRange = patchRangeRecord.base || {};
       return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
-    },
+    }
 
     /**
      * @param {boolean} editMode
      */
     _computeContainerClass(editMode) {
       return editMode ? 'editMode' : '';
-    },
+    }
 
     _computeBlameToggleLabel(loaded, loading) {
       if (loaded) { return 'Hide blame'; }
       return 'Show blame';
-    },
+    }
 
     /**
      * Load and display blame information if it has not already been loaded.
@@ -1091,15 +1099,15 @@
           .catch(() => {
             this._isBlameLoading = false;
           });
-    },
+    }
 
     _computeBlameLoaderClass(isImageDiff) {
       return !isImageDiff ? 'show' : '';
-    },
+    }
 
     _getRevisionInfo(change) {
       return new Gerrit.RevisionInfo(change);
-    },
+    }
 
     _computeFileNum(file, files) {
       // Polymer 2: check for undefined
@@ -1108,7 +1116,7 @@
       }
 
       return files.findIndex(({value}) => value === file) + 1;
-    },
+    }
 
     /**
      * @param {number} fileNum
@@ -1120,16 +1128,16 @@
         return 'show';
       }
       return '';
-    },
+    }
 
     _handleExpandAllDiffContext(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
       this.$.diffHost.expandAllContext();
-    },
+    }
 
     _computeDiffPrefsDisabled(disableDiffPrefs, loggedIn) {
       return disableDiffPrefs || !loggedIn;
-    },
+    }
 
     _handleNextUnreviewedFile(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -1140,10 +1148,12 @@
           .filter(file =>
             (file === this._path || !this._reviewedFiles.has(file)));
       this._navToFile(this._path, unreviewedFiles, 1);
-    },
+    }
 
     _handleReloadingDiffPreference() {
       this._getDiffPreferences();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffView.is, GrDiffView);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index 573d75f..3a5c0bc 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html
index 16e8036..686410c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff-group_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-group</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/web-component-tester/browser.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index aa69248..1446fd4 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -294,13 +294,16 @@
         display: none;
       }
       .lineNum.COVERED {
-         background-color: #E0F2F1;
+         background-color: var(--coverage-covered, #e0f2f1);
       }
       .lineNum.NOT_COVERED {
-        background-color: #FFD1A4;
+        background-color: var(--coverage-not-covered, #ffd1a4);
       }
       .lineNum.PARTIALLY_COVERED {
-        background: linear-gradient(to right bottom, #FFD1A4 0%, #FFD1A4 50%, #E0F2F1 50%, #E0F2F1 100%);
+        background: linear-gradient(to right bottom, var(--coverage-not-covered, #ffd1a4) 0%,
+                                                     var(--coverage-not-covered, #ffd1a4) 50%,
+                                                     var(--coverage-covered, #e0f2f1) 50%,
+                                                     var(--coverage-covered, #e0f2f1) 100%);
       }
 
       /** BEGIN: Select and copy for Polymer 2 */
@@ -344,8 +347,12 @@
         text-align: center;
       }
     </style>
-    <style include="gr-syntax-theme"></style>
-    <style include="gr-ranged-comment-theme"></style>
+    <style include="gr-syntax-theme">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-ranged-comment-theme">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div id="diffHeader" hidden$="[[_computeDiffHeaderHidden(_diffHeaderItems)]]">
       <template
           is="dom-repeat"
@@ -370,7 +377,6 @@
               change-num="[[changeNum]]"
               patch-num="[[patchRange.patchNum]]"
               view-mode="[[viewMode]]"
-              line-wrapping="[[lineWrapping]]"
               is-image-diff="[[isImageDiff]]"
               base-image="[[baseImage]]"
               layers="[[layers]]"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 9c38718..727115b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -91,9 +91,17 @@
 
   const RENDER_DIFF_TABLE_DEBOUNCE_NAME = 'renderDiffTable';
 
-  Polymer({
-    is: 'gr-diff',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrDiff extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-diff'; }
     /**
      * Fired when the user selects a line.
      * @event line-selected
@@ -126,89 +134,90 @@
      * @event diff-context-expanded
      */
 
-    properties: {
-      changeNum: String,
-      noAutoRender: {
-        type: Boolean,
-        value: false,
-      },
-      /** @type {?} */
-      patchRange: Object,
-      path: {
-        type: String,
-        observer: '_pathObserver',
-      },
-      prefs: {
-        type: Object,
-        observer: '_prefsObserver',
-      },
-      projectName: String,
-      displayLine: {
-        type: Boolean,
-        value: false,
-      },
-      isImageDiff: {
-        type: Boolean,
-      },
-      commitRange: Object,
-      hidden: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-      noRenderOnPrefsChange: Boolean,
-      /** @type {!Array<!Gerrit.HoveredRange>} */
-      _commentRanges: {
-        type: Array,
-        value: () => [],
-      },
-      /** @type {!Array<!Gerrit.CoverageRange>} */
-      coverageRanges: {
-        type: Array,
-        value: () => [],
-      },
-      lineWrapping: {
-        type: Boolean,
-        value: false,
-        observer: '_lineWrappingObserver',
-      },
-      viewMode: {
-        type: String,
-        value: DiffViewMode.SIDE_BY_SIDE,
-        observer: '_viewModeObserver',
-      },
+    static get properties() {
+      return {
+        changeNum: String,
+        noAutoRender: {
+          type: Boolean,
+          value: false,
+        },
+        /** @type {?} */
+        patchRange: Object,
+        path: {
+          type: String,
+          observer: '_pathObserver',
+        },
+        prefs: {
+          type: Object,
+          observer: '_prefsObserver',
+        },
+        projectName: String,
+        displayLine: {
+          type: Boolean,
+          value: false,
+        },
+        isImageDiff: {
+          type: Boolean,
+        },
+        commitRange: Object,
+        hidden: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+        noRenderOnPrefsChange: Boolean,
+        /** @type {!Array<!Gerrit.HoveredRange>} */
+        _commentRanges: {
+          type: Array,
+          value: () => [],
+        },
+        /** @type {!Array<!Gerrit.CoverageRange>} */
+        coverageRanges: {
+          type: Array,
+          value: () => [],
+        },
+        lineWrapping: {
+          type: Boolean,
+          value: false,
+          observer: '_lineWrappingObserver',
+        },
+        viewMode: {
+          type: String,
+          value: DiffViewMode.SIDE_BY_SIDE,
+          observer: '_viewModeObserver',
+        },
 
-      /** @type ?Gerrit.LineOfInterest */
-      lineOfInterest: Object,
+        /** @type ?Gerrit.LineOfInterest */
+        lineOfInterest: Object,
 
-      loading: {
-        type: Boolean,
-        value: false,
-        observer: '_loadingChanged',
-      },
+        loading: {
+          type: Boolean,
+          value: false,
+          observer: '_loadingChanged',
+        },
 
-      loggedIn: {
-        type: Boolean,
-        value: false,
-      },
-      diff: {
-        type: Object,
-        observer: '_diffChanged',
-      },
-      _diffHeaderItems: {
-        type: Array,
-        value: [],
-        computed: '_computeDiffHeaderItems(diff.*)',
-      },
-      _diffTableClass: {
-        type: String,
-        value: '',
-      },
-      /** @type {?Object} */
-      baseImage: Object,
-      /** @type {?Object} */
-      revisionImage: Object,
+        loggedIn: {
+          type: Boolean,
+          value: false,
+        },
+        diff: {
+          type: Object,
+          observer: '_diffChanged',
+        },
+        _diffHeaderItems: {
+          type: Array,
+          value: [],
+          computed: '_computeDiffHeaderItems(diff.*)',
+        },
+        _diffTableClass: {
+          type: String,
+          value: '',
+        },
+        /** @type {?Object} */
+        baseImage: Object,
+        /** @type {?Object} */
+        revisionImage: Object,
 
-      /**
+        /**
        * Whether the safety check for large diffs when whole-file is set has
        * been bypassed. If the value is null, then the safety has not been
        * bypassed. If the value is a number, then that number represents the
@@ -216,83 +225,86 @@
        *
        * @type (number|null)
        */
-      _safetyBypass: {
-        type: Number,
-        value: null,
-      },
+        _safetyBypass: {
+          type: Number,
+          value: null,
+        },
 
-      _showWarning: Boolean,
+        _showWarning: Boolean,
 
-      /** @type {?string} */
-      errorMessage: {
-        type: String,
-        value: null,
-      },
+        /** @type {?string} */
+        errorMessage: {
+          type: String,
+          value: null,
+        },
 
-      /** @type {?Object} */
-      blame: {
-        type: Object,
-        value: null,
-        observer: '_blameChanged',
-      },
+        /** @type {?Object} */
+        blame: {
+          type: Object,
+          value: null,
+          observer: '_blameChanged',
+        },
 
-      parentIndex: Number,
+        parentIndex: Number,
 
-      _newlineWarning: {
-        type: String,
-        computed: '_computeNewlineWarning(diff)',
-      },
+        _newlineWarning: {
+          type: String,
+          computed: '_computeNewlineWarning(diff)',
+        },
 
-      _diffLength: Number,
+        _diffLength: Number,
 
-      /**
+        /**
        * Observes comment nodes added or removed after the initial render.
        * Can be used to unregister when the entire diff is (re-)rendered or upon
        * detachment.
        * @type {?PolymerDomApi.ObserveHandle}
        */
-      _incrementalNodeObserver: Object,
+        _incrementalNodeObserver: Object,
 
-      /**
+        /**
        * Observes comment nodes added or removed at any point.
        * Can be used to unregister upon detachment.
        * @type {?PolymerDomApi.ObserveHandle}
        */
-      _nodeObserver: Object,
+        _nodeObserver: Object,
 
-      /** Set by Polymer. */
-      isAttached: Boolean,
-      layers: Array,
-    },
+        /** Set by Polymer. */
+        isAttached: Boolean,
+        layers: Array,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PatchSetBehavior,
-    ],
+    static get observers() {
+      return [
+        '_enableSelectionObserver(loggedIn, isAttached)',
+      ];
+    }
 
-    listeners: {
-      'create-range-comment': '_handleCreateRangeComment',
-      'render-content': '_handleRenderContent',
-    },
-
-    observers: [
-      '_enableSelectionObserver(loggedIn, isAttached)',
-    ],
+    created() {
+      super.created();
+      this.addEventListener('create-range-comment',
+          e => this._handleCreateRangeComment(e));
+      this.addEventListener('render-content',
+          () => this._handleRenderContent());
+    }
 
     attached() {
+      super.attached();
       this._observeNodes();
-    },
+    }
 
     detached() {
+      super.detached();
       this._unobserveIncrementalNodes();
       this._unobserveNodes();
-    },
+    }
 
     showNoChangeMessage(loading, prefs, diffLength) {
       return !loading &&
         prefs && prefs.ignore_whitespace !== 'IGNORE_NONE'
         && diffLength === 0;
-    },
+    }
 
     _enableSelectionObserver(loggedIn, isAttached) {
       // Polymer 2: check for undefined
@@ -307,7 +319,7 @@
         this.unlisten(document, 'selectionchange', '_handleSelectionChange');
         this.unlisten(document, 'mouseup', '_handleMouseUp');
       }
-    },
+    }
 
     _handleSelectionChange() {
       // Because of shadow DOM selections, we handle the selectionchange here,
@@ -315,7 +327,7 @@
       // corresponding range is determined and normalized.
       const selection = this._getShadowOrDocumentSelection();
       this.$.highlights.handleSelectionChange(selection, false);
-    },
+    }
 
     _handleMouseUp(e) {
       // To handle double-click outside of text creating comments, we check on
@@ -323,7 +335,7 @@
       // can't do that on selection change since the user may still be dragging.
       const selection = this._getShadowOrDocumentSelection();
       this.$.highlights.handleSelectionChange(selection, true);
-    },
+    }
 
     /** Gets the current selection, preferring the shadow DOM selection. */
     _getShadowOrDocumentSelection() {
@@ -334,7 +346,7 @@
       return this.root.getSelection ?
         this.root.getSelection() :
         document.getSelection();
-    },
+    }
 
     _observeNodes() {
       this._nodeObserver = Polymer.dom(this).observeNodes(info => {
@@ -343,7 +355,7 @@
         this._updateRanges(addedThreadEls, removedThreadEls);
         this._redispatchHoverEvents(addedThreadEls);
       });
-    },
+    }
 
     _updateRanges(addedThreadEls, removedThreadEls) {
       function commentRangeFromThreadEl(threadEl) {
@@ -369,7 +381,7 @@
       if (addedCommentRanges && addedCommentRanges.length) {
         this.push('_commentRanges', ...addedCommentRanges);
       }
-    },
+    }
 
     /**
      * The key locations based on the comments and line of interests,
@@ -400,7 +412,7 @@
         }
       }
       return keyLocations;
-    },
+    }
 
     // Dispatch events that are handled by the gr-diff-highlight.
     _redispatchHoverEvents(addedThreadEls) {
@@ -414,13 +426,13 @@
               'comment-thread-mouseleave', {bubbles: true, composed: true}));
         });
       }
-    },
+    }
 
     /** Cancel any remaining diff builder rendering work. */
     cancel() {
       this.$.diffBuilder.cancel();
       this.cancelDebouncer(RENDER_DIFF_TABLE_DEBOUNCE_NAME);
-    },
+    }
 
     /** @return {!Array<!HTMLElement>} */
     getCursorStops() {
@@ -430,16 +442,16 @@
 
       return Array.from(
           Polymer.dom(this.root).querySelectorAll('.diff-row'));
-    },
+    }
 
     /** @return {boolean} */
     isRangeSelected() {
-      return this.$.highlights.isRangeSelected();
-    },
+      return !!this.$.highlights.selectedRange;
+    }
 
     toggleLeftDiff() {
       this.toggleClass('no-left');
-    },
+    }
 
     _blameChanged(newValue) {
       this.$.diffBuilder.setBlame(newValue);
@@ -448,7 +460,7 @@
       } else {
         this.classList.remove('showBlame');
       }
-    },
+    }
 
     /** @return {string} */
     _computeContainerClass(loggedIn, viewMode, displayLine) {
@@ -473,7 +485,7 @@
         classes.push('displayLine');
       }
       return classes.join(' ');
-    },
+    }
 
     _handleTap(e) {
       const el = Polymer.dom(e).localTarget;
@@ -491,7 +503,7 @@
         const target = this.$.diffBuilder.getLineElByChild(el);
         if (target) { this._selectLine(target); }
       }
-    },
+    }
 
     _selectLine(el) {
       this.fire('line-selected', {
@@ -499,7 +511,7 @@
         number: el.getAttribute('data-value'),
         path: this.path,
       });
-    },
+    }
 
     addDraftAtLine(el) {
       this._selectLine(el);
@@ -515,18 +527,29 @@
         }
       }
       this._createComment(el, lineNum);
-    },
+    }
+
+    createRangeComment() {
+      if (!this.isRangeSelected()) {
+        throw Error('Selection is needed for new range comment');
+      }
+      const {side, range} = this.$.highlights.selectedRange;
+      this._createCommentForSelection(side, range);
+    }
+
+    _createCommentForSelection(side, range) {
+      const lineNum = range.end_line;
+      const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);
+      if (this._isValidElForComment(lineEl)) {
+        this._createComment(lineEl, lineNum, side, range);
+      }
+    }
 
     _handleCreateRangeComment(e) {
       const range = e.detail.range;
       const side = e.detail.side;
-      const lineNum = range.end_line;
-      const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);
-
-      if (this._isValidElForComment(lineEl)) {
-        this._createComment(lineEl, lineNum, side, range);
-      }
-    },
+      this._createCommentForSelection(side, range);
+    }
 
     /** @return {boolean} */
     _isValidElForComment(el) {
@@ -550,7 +573,7 @@
         return false;
       }
       return true;
-    },
+    }
 
     /**
      * @param {!Object} lineEl
@@ -578,11 +601,11 @@
           range,
         },
       }));
-    },
+    }
 
     _getThreadGroupForLine(contentEl) {
       return contentEl.querySelector('.thread-group');
-    },
+    }
 
     /**
      * Gets or creates a comment thread group for a specific line and side on a
@@ -601,7 +624,7 @@
         contentEl.appendChild(threadGroupEl);
       }
       return threadGroupEl;
-    },
+    }
 
     /**
      * The value to be used for the patch number of new comments created at the
@@ -627,7 +650,7 @@
         patchNum = this.patchRange.basePatchNum;
       }
       return patchNum;
-    },
+    }
 
     /** @return {boolean} */
     _getIsParentCommentByLineAndContent(lineEl, contentEl) {
@@ -638,7 +661,7 @@
         return true;
       }
       return false;
-    },
+    }
 
     /** @return {string} */
     _getCommentSideByLineAndContent(lineEl, contentEl) {
@@ -648,7 +671,7 @@
         side = 'left';
       }
       return side;
-    },
+    }
 
     _prefsObserver(newPrefs, oldPrefs) {
       // Scan the preference objects one level deep to see if they differ.
@@ -664,16 +687,16 @@
       if (differ) {
         this._prefsChanged(newPrefs);
       }
-    },
+    }
 
     _pathObserver() {
       // Call _prefsChanged(), because line-limit style value depends on path.
       this._prefsChanged(this.prefs);
-    },
+    }
 
     _viewModeObserver() {
       this._prefsChanged(this.prefs);
-    },
+    }
 
     /** @param {boolean} newValue */
     _loadingChanged(newValue) {
@@ -684,11 +707,11 @@
         this._showWarning = false;
         this.clearDiffContent();
       }
-    },
+    }
 
     _lineWrappingObserver() {
       this._prefsChanged(this.prefs);
-    },
+    }
 
     _prefsChanged(prefs) {
       if (!prefs) { return; }
@@ -719,14 +742,14 @@
       if (this.diff && !this.noRenderOnPrefsChange) {
         this._debounceRenderDiffTable();
       }
-    },
+    }
 
     _diffChanged(newValue) {
       if (newValue) {
         this._diffLength = this.getDiffLength(newValue);
         this._debounceRenderDiffTable();
       }
-    },
+    }
 
     /**
      * When called multiple times from the same microtask, will call
@@ -741,7 +764,7 @@
     _debounceRenderDiffTable() {
       this.debounce(
           RENDER_DIFF_TABLE_DEBOUNCE_NAME, () => this._renderDiffTable());
-    },
+    }
 
     _renderDiffTable() {
       this._unobserveIncrementalNodes();
@@ -771,7 +794,7 @@
                   detail: {contentRendered: true},
                 }));
           });
-    },
+    }
 
     _handleRenderContent() {
       this._incrementalNodeObserver = Polymer.dom(this).observeNodes(info => {
@@ -810,19 +833,19 @@
           lastEl.replaceWith(lastEl);
         }
       });
-    },
+    }
 
     _unobserveIncrementalNodes() {
       if (this._incrementalNodeObserver) {
         Polymer.dom(this).unobserveNodes(this._incrementalNodeObserver);
       }
-    },
+    }
 
     _unobserveNodes() {
       if (this._nodeObserver) {
         Polymer.dom(this).unobserveNodes(this._nodeObserver);
       }
-    },
+    }
 
     /**
      * Get the preferences object including the safety bypass context (if any).
@@ -832,12 +855,12 @@
         return Object.assign({}, this.prefs, {context: this._safetyBypass});
       }
       return this.prefs;
-    },
+    }
 
     clearDiffContent() {
       this._unobserveIncrementalNodes();
       this.$.diffTable.innerHTML = null;
-    },
+    }
 
     /** @return {!Array} */
     _computeDiffHeaderItems(diffInfoRecord) {
@@ -850,27 +873,27 @@
             item.startsWith('--- ') ||
             item === 'Binary files differ');
       });
-    },
+    }
 
     /** @return {boolean} */
     _computeDiffHeaderHidden(items) {
       return items.length === 0;
-    },
+    }
 
     _handleFullBypass() {
       this._safetyBypass = FULL_CONTEXT;
       this._debounceRenderDiffTable();
-    },
+    }
 
     _handleLimitedBypass() {
       this._safetyBypass = LIMITED_CONTEXT;
       this._debounceRenderDiffTable();
-    },
+    }
 
     /** @return {string} */
     _computeWarningClass(showWarning) {
       return showWarning ? 'warn' : '';
-    },
+    }
 
     /**
      * @param {string} errorMessage
@@ -878,11 +901,11 @@
      */
     _computeErrorClass(errorMessage) {
       return errorMessage ? 'showError' : '';
-    },
+    }
 
     expandAllContext() {
       this._handleFullBypass();
-    },
+    }
 
     /**
      * Find the last chunk for the given side.
@@ -918,7 +941,7 @@
       if (chunkIndex === -1) { return null; }
 
       return chunk;
-    },
+    }
 
     /**
      * Check whether the specified side of the diff has a trailing newline.
@@ -939,7 +962,7 @@
         lines = leftSide ? chunk.a : chunk.b;
       }
       return lines[lines.length - 1] === '';
-    },
+    }
 
     /**
      * @param {!Object} diff
@@ -957,7 +980,7 @@
       }
       if (!messages.length) { return null; }
       return messages.join(' — ');
-    },
+    }
 
     /**
      * @param {string} warning
@@ -967,7 +990,7 @@
     _computeNewlineWarningClass(warning, loading) {
       if (loading || !warning) { return 'newlineWarning hidden'; }
       return 'newlineWarning';
-    },
+    }
 
     /**
      * Get the approximate length of the diff as the sum of the maximum
@@ -986,6 +1009,8 @@
               sec.hasOwnProperty('b') ? sec.b.length : 0);
         }
       }, 0);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiff.is, GrDiff);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index 52a29f9..2805eb4 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
index 52a107d..14148a9 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.js
@@ -21,6 +21,9 @@
   const PATCH_DESC_MAX_LENGTH = 500;
 
   /**
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  /**
    * Fired when the patch range changes
    *
    * @event patch-range-change
@@ -28,42 +31,47 @@
    * @property {string} patchNum
    * @property {string} basePatchNum
    */
+  class GrPatchRangeSelect extends Polymer.mixinBehaviors( [
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-patch-range-select'; }
 
-  Polymer({
-    is: 'gr-patch-range-select',
-
-    properties: {
-      availablePatches: Array,
-      _baseDropdownContent: {
-        type: Object,
-        computed: '_computeBaseDropdownContent(availablePatches, patchNum,' +
+    static get properties() {
+      return {
+        availablePatches: Array,
+        _baseDropdownContent: {
+          type: Object,
+          computed: '_computeBaseDropdownContent(availablePatches, patchNum,' +
             '_sortedRevisions, changeComments, revisionInfo)',
-      },
-      _patchDropdownContent: {
-        type: Object,
-        computed: '_computePatchDropdownContent(availablePatches,' +
+        },
+        _patchDropdownContent: {
+          type: Object,
+          computed: '_computePatchDropdownContent(availablePatches,' +
             'basePatchNum, _sortedRevisions, changeComments)',
-      },
-      changeNum: String,
-      changeComments: Object,
-      /** @type {{ meta_a: !Array, meta_b: !Array}} */
-      filesWeblinks: Object,
-      patchNum: String,
-      basePatchNum: String,
-      revisions: Object,
-      revisionInfo: Object,
-      _sortedRevisions: Array,
-    },
+        },
+        changeNum: String,
+        changeComments: Object,
+        /** @type {{ meta_a: !Array, meta_b: !Array}} */
+        filesWeblinks: Object,
+        patchNum: String,
+        basePatchNum: String,
+        revisions: Object,
+        revisionInfo: Object,
+        _sortedRevisions: Array,
+      };
+    }
 
-    observers: [
-      '_updateSortedRevisions(revisions.*)',
-    ],
-
-    behaviors: [Gerrit.PatchSetBehavior],
+    static get observers() {
+      return [
+        '_updateSortedRevisions(revisions.*)',
+      ];
+    }
 
     _getShaForPatch(patch) {
       return patch.sha.substring(0, 10);
-    },
+    }
 
     _computeBaseDropdownContent(availablePatches, patchNum, _sortedRevisions,
         changeComments, revisionInfo) {
@@ -111,13 +119,13 @@
       }
 
       return dropdownContent;
-    },
+    }
 
     _computeMobileText(patchNum, changeComments, revisions) {
       return `${patchNum}` +
           `${this._computePatchSetCommentsString(changeComments, patchNum)}` +
           `${this._computePatchSetDescription(revisions, patchNum, true)}`;
-    },
+    }
 
     _computePatchDropdownContent(availablePatches, basePatchNum,
         _sortedRevisions, changeComments) {
@@ -143,13 +151,13 @@
         }));
       }
       return dropdownContent;
-    },
+    }
 
     _computeText(patchNum, prefix, changeComments, sha) {
       return `${prefix}${patchNum}` +
         `${this._computePatchSetCommentsString(changeComments, patchNum)}`
           + (` | ${sha}`);
-    },
+    }
 
     _createDropdownEntry(patchNum, prefix, sortedRevisions, changeComments,
         sha) {
@@ -167,12 +175,12 @@
         entry['date'] = date;
       }
       return entry;
-    },
+    }
 
     _updateSortedRevisions(revisionsRecord) {
       const revisions = revisionsRecord.base;
       this._sortedRevisions = this.sortRevisions(Object.values(revisions));
-    },
+    }
 
     /**
      * The basePatchNum should always be <= patchNum -- because sortedRevisions
@@ -185,7 +193,7 @@
     _computeLeftDisabled(basePatchNum, patchNum, sortedRevisions) {
       return this.findSortedIndex(basePatchNum, sortedRevisions) <=
           this.findSortedIndex(patchNum, sortedRevisions);
-    },
+    }
 
     /**
      * The basePatchNum should always be <= patchNum -- because sortedRevisions
@@ -214,7 +222,7 @@
 
       return this.findSortedIndex(basePatchNum, sortedRevisions) <=
           this.findSortedIndex(patchNum, sortedRevisions);
-    },
+    }
 
     _computePatchSetCommentsString(changeComments, patchNum) {
       if (!changeComments) { return; }
@@ -235,7 +243,7 @@
           // Add a comma + space if both comments and unresolved
           (commentString && unresolvedString ? ', ' : '') +
           `${unresolvedString})`;
-    },
+    }
 
     /**
      * @param {!Array} revisions
@@ -247,7 +255,7 @@
       return (rev && rev.description) ?
         (opt_addFrontSpace ? ' ' : '') +
           rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
-    },
+    }
 
     /**
      * @param {!Array} revisions
@@ -256,7 +264,7 @@
     _computePatchSetDate(revisions, patchNum) {
       const rev = this.getRevisionByPatchNum(revisions, patchNum);
       return rev ? rev.created : undefined;
-    },
+    }
 
     /**
      * Catches value-change events from the patchset dropdowns and determines
@@ -274,6 +282,8 @@
 
       this.dispatchEvent(
           new CustomEvent('patch-range-change', {detail, bubbles: false}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPatchRangeSelect.is, GrPatchRangeSelect);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html
index ee893ee..81897cd 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-patch-range-select</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
index 2e74ff4..7ee6492 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer.js
@@ -23,9 +23,10 @@
   const RANGE_HIGHLIGHT = 'style-scope gr-diff range';
   const HOVER_HIGHLIGHT = 'style-scope gr-diff rangeHighlight';
 
-  Polymer({
-    is: 'gr-ranged-comment-layer',
-
+  class GrRangedCommentLayer extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-ranged-comment-layer'; }
     /**
      * Fired when the range in a range comment was malformed and had to be
      * normalized.
@@ -35,26 +36,30 @@
      * @event normalize-range
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {!Array<!Gerrit.HoveredRange>} */
-      commentRanges: Array,
-      _listeners: {
-        type: Array,
-        value() { return []; },
-      },
-      _rangesMap: {
-        type: Object,
-        value() { return {left: {}, right: {}}; },
-      },
-    },
+        commentRanges: Array,
+        _listeners: {
+          type: Array,
+          value() { return []; },
+        },
+        _rangesMap: {
+          type: Object,
+          value() { return {left: {}, right: {}}; },
+        },
+      };
+    }
 
-    observers: [
-      '_handleCommentRangesChange(commentRanges.*)',
-    ],
+    static get observers() {
+      return [
+        '_handleCommentRangesChange(commentRanges.*)',
+      ];
+    }
 
     get styleModuleName() {
       return 'gr-ranged-comment-styles';
-    },
+    }
 
     /**
      * Layer method to add annotations to a line.
@@ -81,7 +86,7 @@
             range.end - range.start,
             range.hovering ? HOVER_HIGHLIGHT : RANGE_HIGHLIGHT);
       }
-    },
+    }
 
     /**
      * Register a listener for layer updates.
@@ -91,7 +96,7 @@
      */
     addListener(fn) {
       this._listeners.push(fn);
-    },
+    }
 
     /**
      * Notify Layer listeners of changes to annotations.
@@ -103,7 +108,7 @@
       for (const listener of this._listeners) {
         listener(start, end, side);
       }
-    },
+    }
 
     /**
      * Handle change in the ranges by updating the ranges maps and by
@@ -161,7 +166,7 @@
           }
         }
       }
-    },
+    }
 
     _updateRangesMap(side, range, hovering, operation) {
       const forSide = this._rangesMap[side] || (this._rangesMap[side] = {});
@@ -172,7 +177,7 @@
         operation(forLine, start, end, hovering);
       }
       this._notifyUpdateRange(range.start_line, range.end_line, side);
-    },
+    }
 
     _getRangesForLine(line, side) {
       const lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
@@ -200,6 +205,8 @@
           })
           // Sort the ranges so that hovering highlights are on top.
           .sort((a, b) => a.hovering && !b.hovering ? 1 : 0);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRangedCommentLayer.is, GrRangedCommentLayer);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
index 9d207a5..4ed744b 100644
--- a/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-ranged-comment-layer/gr-ranged-comment-layer_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-ranged-comment-layer</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
index b1b3e0f..3ef9105 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box.js
@@ -17,48 +17,38 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-selection-action-box',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrSelectionActionBox extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-selection-action-box'; }
     /**
-     * Fired when the comment creation action was taken (hotkey, click).
+     * Fired when the comment creation action was taken (click).
      *
-     * @event create-range-comment
+     * @event create-comment-requested
      */
 
-    properties: {
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      range: {
-        type: Object,
-        value: {
-          start_line: NaN,
-          start_character: NaN,
-          end_line: NaN,
-          end_character: NaN,
+    static get properties() {
+      return {
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
         },
-      },
-      positionBelow: Boolean,
-      side: {
-        type: String,
-        value: '',
-      },
-    },
+        positionBelow: Boolean,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
+    created() {
+      super.created();
 
-    listeners: {
-      mousedown: '_handleMouseDown', // See https://crbug.com/gerrit/4767
-    },
-
-    keyBindings: {
-      c: '_handleCKey',
-    },
+      // See https://crbug.com/gerrit/4767
+      this.addEventListener('mousedown',
+          e => this._handleMouseDown(e));
+    }
 
     placeAbove(el) {
       Polymer.dom.flush();
@@ -69,7 +59,7 @@
           rect.top - parentRect.top - boxRect.height - 6 + 'px';
       this.style.left =
           rect.left - parentRect.left + (rect.width - boxRect.width) / 2 + 'px';
-    },
+    }
 
     placeBelow(el) {
       Polymer.dom.flush();
@@ -80,14 +70,14 @@
       rect.top - parentRect.top + boxRect.height - 6 + 'px';
       this.style.left =
       rect.left - parentRect.left + (rect.width - boxRect.width) / 2 + 'px';
-    },
+    }
 
     _getParentBoundingClientRect() {
       // With native shadow DOM, the parent is the shadow root, not the gr-diff
       // element
       const parent = this.parentElement || this.parentNode.host;
       return parent.getBoundingClientRect();
-    },
+    }
 
     _getTargetBoundingRect(el) {
       let rect;
@@ -100,25 +90,15 @@
         rect = el.getBoundingClientRect();
       }
       return rect;
-    },
-
-    _handleCKey(e) {
-      if (this.shouldSuppressKeyboardShortcut(e) ||
-          this.modifierPressed(e)) { return; }
-
-      e.preventDefault();
-      this._fireCreateComment();
-    },
+    }
 
     _handleMouseDown(e) {
       if (e.button !== 0) { return; } // 0 = main button
       e.preventDefault();
       e.stopPropagation();
-      this._fireCreateComment();
-    },
+      this.fire('create-comment-requested');
+    }
+  }
 
-    _fireCreateComment() {
-      this.fire('create-range-comment', {side: this.side, range: this.range});
-    },
-  });
+  customElements.define(GrSelectionActionBox.is, GrSelectionActionBox);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
index b950e7b..57adf32 100644
--- a/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-selection-action-box/gr-selection-action-box_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-selection-action-box</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -59,11 +59,6 @@
       assert.isFalse(element.fire.called);
     });
 
-    test('reacts to hotkey', () => {
-      MockInteractions.pressAndReleaseKeyOn(document.body, 67, null, 'c');
-      assert.isTrue(element.fire.called);
-    });
-
     suite('mousedown reacts only to main button', () => {
       let e;
 
@@ -73,40 +68,22 @@
           preventDefault: sandbox.stub(),
           stopPropagation: sandbox.stub(),
         };
-        sandbox.stub(element, '_fireCreateComment');
       });
 
       test('event handled if main button', () => {
         element._handleMouseDown(e);
         assert.isTrue(e.preventDefault.called);
+        assert(element.fire.calledWithExactly('create-comment-requested'));
       });
 
       test('event ignored if not main button', () => {
         e.button = 1;
         element._handleMouseDown(e);
         assert.isFalse(e.preventDefault.called);
+        assert.isFalse(element.fire.called);
       });
     });
 
-    test('event fired contains playload', () => {
-      const side = 'left';
-      const range = {
-        start_line: 1,
-        start_character: 11,
-        end_line: 2,
-        end_character: 42,
-      };
-      element.side = 'left';
-      element.range = range;
-      MockInteractions.pressAndReleaseKeyOn(document.body, 67, null, 'c');
-      assert(element.fire.calledWithExactly(
-          'create-range-comment',
-          {
-            side,
-            range,
-          }));
-    });
-
     suite('placeAbove', () => {
       let target;
 
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
index 6c7d582..b0947cd 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
@@ -130,54 +130,58 @@
   const GO_BACKSLASH_LITERAL = '\'\\\\\'';
   const GLOBAL_LT_PATTERN = /</g;
 
-  Polymer({
-    is: 'gr-syntax-layer',
+  class GrSyntaxLayer extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-syntax-layer'; }
 
-    properties: {
-      diff: {
-        type: Object,
-        observer: '_diffChanged',
-      },
-      enabled: {
-        type: Boolean,
-        value: true,
-      },
-      _baseRanges: {
-        type: Array,
-        value() { return []; },
-      },
-      _revisionRanges: {
-        type: Array,
-        value() { return []; },
-      },
-      _baseLanguage: String,
-      _revisionLanguage: String,
-      _listeners: {
-        type: Array,
-        value() { return []; },
-      },
-      /** @type {?number} */
-      _processHandle: Number,
-      /**
+    static get properties() {
+      return {
+        diff: {
+          type: Object,
+          observer: '_diffChanged',
+        },
+        enabled: {
+          type: Boolean,
+          value: true,
+        },
+        _baseRanges: {
+          type: Array,
+          value() { return []; },
+        },
+        _revisionRanges: {
+          type: Array,
+          value() { return []; },
+        },
+        _baseLanguage: String,
+        _revisionLanguage: String,
+        _listeners: {
+          type: Array,
+          value() { return []; },
+        },
+        /** @type {?number} */
+        _processHandle: Number,
+        /**
        * The promise last returned from `process()` while the asynchronous
        * processing is running - `null` otherwise. Provides a `cancel()`
        * method that rejects it with `{isCancelled: true}`.
        * @type {?Object}
        */
-      _processPromise: {
-        type: Object,
-        value: null,
-      },
-      _hljs: Object,
-    },
+        _processPromise: {
+          type: Object,
+          value: null,
+        },
+        _hljs: Object,
+      };
+    }
 
     addListener(fn) {
       this.push('_listeners', fn);
-    },
+    }
 
     removeListener(fn) {
       this._listeners = this._listeners.filter(f => f != fn);
-    },
+    }
 
     /**
      * Annotation layer method to add syntax annotations to the given element
@@ -214,14 +218,14 @@
         GrAnnotation.annotateElement(
             el, range.start, range.length, range.className);
       }
-    },
+    }
 
     _getLanguage(diffFileMetaInfo) {
       // The Gerrit API provides only content-type, but for other users of
       // gr-diff it may be more convenient to specify the language directly.
       return diffFileMetaInfo.language ||
           LANGUAGE_MAP[diffFileMetaInfo.content_type];
-    },
+    }
 
     /**
      * Start processing syntax for the loaded diff and notify layer listeners
@@ -298,7 +302,7 @@
           }));
       return this._processPromise
           .finally(() => { this._processPromise = null; });
-    },
+    }
 
     /**
      * Cancel any asynchronous syntax processing jobs.
@@ -311,13 +315,13 @@
       if (this._processPromise) {
         this._processPromise.cancel();
       }
-    },
+    }
 
     _diffChanged() {
       this._cancel();
       this._baseRanges = [];
       this._revisionRanges = [];
-    },
+    }
 
     /**
      * Take a string of HTML with the (potentially nested) syntax markers
@@ -339,7 +343,7 @@
       const ranges = this._rangesFromElement(div, 0);
       rangesCache.set(str, ranges);
       return ranges;
-    },
+    }
 
     _rangesFromElement(elem, offset) {
       let result = [];
@@ -362,7 +366,7 @@
         offset += nodeLength;
       }
       return result;
-    },
+    }
 
     /**
      * For a given state, process the syntax for the next line (or pair of
@@ -412,7 +416,7 @@
             this._rangesFromString(result.value, rangesCache));
         state.revisionContext = result.top;
       }
-    },
+    }
 
     /**
      * Ad hoc fixes for HLJS parsing bugs. Rewrite lines of code in constrained
@@ -479,7 +483,7 @@
       }
 
       return line;
-    },
+    }
 
     /**
      * Tells whether the state has exhausted its current section.
@@ -494,7 +498,7 @@
         return (!section.a || state.lineIndex >= section.a.length) &&
             (!section.b || state.lineIndex >= section.b.length);
       }
-    },
+    }
 
     /**
      * For a given state, notify layer listeners of any processed line ranges
@@ -516,18 +520,20 @@
             'right');
         state.lastNotify.right = state.lineNums.right;
       }
-    },
+    }
 
     _notifyRange(start, end, side) {
       for (const fn of this._listeners) {
         fn(start, end, side);
       }
-    },
+    }
 
     _loadHLJS() {
       return this.$.libLoader.getHLJS().then(hljs => {
         this._hljs = hljs;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSyntaxLayer.is, GrSyntaxLayer);
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html
index 4e3492f..926a6bc 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-syntax-layer</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html
index 5072b9d..5ae679e 100644
--- a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.html
@@ -25,8 +25,12 @@
 
 <dom-module id="gr-documentation-search">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-table-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-table-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <gr-list-view
         filter="[[_filter]]"
         items=false
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js
index f850b9d..779b16f 100644
--- a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search.js
@@ -17,50 +17,56 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-documentation-search',
+  /**
+    * @appliesMixin Gerrit.ListViewMixin
+    */
+  class GrDocumentationSearch extends Polymer.mixinBehaviors( [
+    Gerrit.ListViewBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-documentation-search'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      _path: {
-        type: String,
-        readOnly: true,
-        value: '/Documentation',
-      },
-      _documentationSearches: Array,
+        _path: {
+          type: String,
+          readOnly: true,
+          value: '/Documentation',
+        },
+        _documentationSearches: Array,
 
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _filter: {
-        type: String,
-        value: '',
-      },
-    },
-
-    behaviors: [
-      Gerrit.ListViewBehavior,
-    ],
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _filter: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this.dispatchEvent(
           new CustomEvent('title-change', {title: 'Documentation Search'}));
-    },
+    }
 
     _paramsChanged(params) {
       this._loading = true;
       this._filter = this.getFilterValue(params);
 
       return this._getDocumentationSearches(this._filter);
-    },
+    }
 
     _getDocumentationSearches(filter) {
       this._documentationSearches = [];
@@ -71,11 +77,13 @@
             this._documentationSearches = searches;
             this._loading = false;
           });
-    },
+    }
 
     _computeSearchUrl(url) {
       if (!url) { return ''; }
       return this.getBaseUrl() + '/' + url;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDocumentationSearch.is, GrDocumentationSearch);
 })();
diff --git a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
index 84298e2..688a9e6 100644
--- a/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
+++ b/polygerrit-ui/app/elements/documentation/gr-documentation-search/gr-documentation-search_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-documentation-search</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
index ed96bb2..ce9db61 100644
--- a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
+++ b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor.js
@@ -17,23 +17,28 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-default-editor',
-
+  class GrDefaultEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-default-editor'; }
     /**
      * Fired when the content of the editor changes.
      *
      * @event content-change
      */
 
-    properties: {
-      fileContent: String,
-    },
+    static get properties() {
+      return {
+        fileContent: String,
+      };
+    }
 
     _handleTextareaInput(e) {
       this.dispatchEvent(new CustomEvent(
           'content-change',
           {detail: {value: e.target.value}, bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDefaultEditor.is, GrDefaultEditor);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html
index c986e7c..4635b1c 100644
--- a/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-default-editor/gr-default-editor_test.html
@@ -17,7 +17,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-default-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-constants.html b/polygerrit-ui/app/elements/edit/gr-edit-constants.html
index d526ccd..5895124 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-constants.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-constants.html
@@ -22,7 +22,7 @@
 
     // Order corresponds to order in the UI.
     GrEditConstants.Actions = {
-      OPEN: {label: 'Open', id: 'open'},
+      OPEN: {label: 'Add/Open', id: 'open'},
       DELETE: {label: 'Delete', id: 'delete'},
       RENAME: {label: 'Rename', id: 'rename'},
       RESTORE: {label: 'Restore', id: 'restore'},
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.html b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.html
index 52692a7..cb950da 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.html
@@ -55,21 +55,13 @@
       gr-dialog .main > iron-input{
         width: 100%;
       }
-      gr-autocomplete {
-        --gr-autocomplete: {
-          border: 1px solid var(--border-color);
-          border-radius: var(--border-radius);
-          height: 2em;
-          padding: 0 var(--spacing-xs);
-        }
-      }
       input {
         border: 1px solid var(--border-color);
         border-radius: var(--border-radius);
-        height: 2em;
         margin: var(--spacing-m) 0;
-        padding: 0 var(--spacing-xs);
+        padding: var(--spacing-s);
         width: 100%;
+        box-sizing: content-box;
       }
       @media screen and (max-width: 50em) {
         gr-dialog {
@@ -89,12 +81,12 @@
           id="openDialog"
           class="invisible dialog"
           disabled$="[[!_isValidPath(_path)]]"
-          confirm-label="Open"
+          confirm-label="Confirm"
           confirm-on-enter
           on-confirm="_handleOpenConfirm"
           on-cancel="_handleDialogCancel">
         <div class="header" slot="header">
-          Open an existing or new file
+          Add a new file or open an existing file
         </div>
         <div class="main" slot="main">
           <gr-autocomplete
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
index 32aad5a..6a585e1 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.js
@@ -17,47 +17,52 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-edit-controls',
+  /**
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrEditControls extends Polymer.mixinBehaviors( [
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-edit-controls'; }
 
-    properties: {
-      change: Object,
-      patchNum: String,
+    static get properties() {
+      return {
+        change: Object,
+        patchNum: String,
 
-      /**
+        /**
        * TODO(kaspern): by default, the RESTORE action should be hidden in the
        * file-list as it is a per-file action only. Remove this default value
        * when the Actions dictionary is moved to a shared constants file and
        * use the hiddenActions property in the parent component.
        */
-      hiddenActions: {
-        type: Array,
-        value() { return [GrEditConstants.Actions.RESTORE.id]; },
-      },
-
-      _actions: {
-        type: Array,
-        value() { return Object.values(GrEditConstants.Actions); },
-      },
-      _path: {
-        type: String,
-        value: '',
-      },
-      _newPath: {
-        type: String,
-        value: '',
-      },
-      _query: {
-        type: Function,
-        value() {
-          return this._queryFiles.bind(this);
+        hiddenActions: {
+          type: Array,
+          value() { return [GrEditConstants.Actions.RESTORE.id]; },
         },
-      },
-    },
 
-    behaviors: [
-      Gerrit.PatchSetBehavior,
-    ],
+        _actions: {
+          type: Array,
+          value() { return Object.values(GrEditConstants.Actions); },
+        },
+        _path: {
+          type: String,
+          value: '',
+        },
+        _newPath: {
+          type: String,
+          value: '',
+        },
+        _query: {
+          type: Function,
+          value() {
+            return this._queryFiles.bind(this);
+          },
+        },
+      };
+    }
 
     _handleTap(e) {
       e.preventDefault();
@@ -76,7 +81,7 @@
           this.openRestoreDialog();
           return;
       }
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -84,7 +89,7 @@
     openOpenDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.openDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -92,7 +97,7 @@
     openDeleteDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.deleteDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -100,7 +105,7 @@
     openRenameDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.renameDialog);
-    },
+    }
 
     /**
      * @param {string=} opt_path
@@ -108,7 +113,7 @@
     openRestoreDialog(opt_path) {
       if (opt_path) { this._path = opt_path; }
       return this._showDialog(this.$.restoreDialog);
-    },
+    }
 
     /**
      * Given a path string, checks that it is a valid file path.
@@ -118,11 +123,11 @@
     _isValidPath(path) {
       // Double negation needed for strict boolean return type.
       return !!path.length && !path.endsWith('/');
-    },
+    }
 
     _computeRenameDisabled(path, newPath) {
       return this._isValidPath(path) && this._isValidPath(newPath);
-    },
+    }
 
     /**
      * Given a dom event, gets the dialog that lies along this event path.
@@ -134,7 +139,7 @@
         if (!element.classList) { return false; }
         return element.classList.contains('dialog');
       });
-    },
+    }
 
     _showDialog(dialog) {
       // Some dialogs may not fire their on-close event when closed in certain
@@ -148,12 +153,12 @@
         if (autocomplete) { autocomplete.focus(); }
         this.async(() => { this.$.overlay.center(); }, 1);
       });
-    },
+    }
 
     _hideAllDialogs() {
       const dialogs = Polymer.dom(this.root).querySelectorAll('.dialog');
       for (const dialog of dialogs) { this._closeDialog(dialog); }
-    },
+    }
 
     /**
      * @param {Element|undefined} dialog
@@ -175,18 +180,18 @@
 
       dialog.classList.toggle('invisible', true);
       return this.$.overlay.close();
-    },
+    }
 
     _handleDialogCancel(e) {
       this._closeDialog(this._getDialogFromEvent(e));
-    },
+    }
 
     _handleOpenConfirm(e) {
       const url = Gerrit.Nav.getEditUrlForDiff(this.change, this._path,
           this.patchNum);
       Gerrit.Nav.navigateToRelativeUrl(url);
       this._closeDialog(this._getDialogFromEvent(e), true);
-    },
+    }
 
     _handleDeleteConfirm(e) {
       // Get the dialog before the api call as the event will change during bubbling
@@ -198,7 +203,7 @@
             this._closeDialog(dialog, true);
             Gerrit.Nav.navigateToChange(this.change);
           });
-    },
+    }
 
     _handleRestoreConfirm(e) {
       const dialog = this._getDialogFromEvent(e);
@@ -208,7 +213,7 @@
             this._closeDialog(dialog, true);
             Gerrit.Nav.navigateToChange(this.change);
           });
-    },
+    }
 
     _handleRenameConfirm(e) {
       const dialog = this._getDialogFromEvent(e);
@@ -218,17 +223,19 @@
         this._closeDialog(dialog, true);
         Gerrit.Nav.navigateToChange(this.change);
       });
-    },
+    }
 
     _queryFiles(input) {
       return this.$.restAPI.queryChangeFiles(this.change._number,
           this.patchNum, input).then(res => res.map(file => {
         return {name: file};
       }));
-    },
+    }
 
     _computeIsInvisible(id, hiddenActions) {
       return hiddenActions.includes(id) ? 'invisible' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditControls.is, GrEditControls);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html
index dd8cb74..2d7dc9c 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.html
@@ -17,7 +17,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-edit-controls</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
index 250816b..ddd2d29 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
+++ b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls.js
@@ -17,38 +17,41 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-edit-file-controls',
-
+  class GrEditFileControls extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-edit-file-controls'; }
     /**
      * Fired when an action in the overflow menu is tapped.
      *
      * @event file-action-tap
      */
 
-    properties: {
-      filePath: String,
-      _allFileActions: {
-        type: Array,
-        value: () => Object.values(GrEditConstants.Actions),
-      },
-      _fileActions: {
-        type: Array,
-        computed: '_computeFileActions(_allFileActions)',
-      },
-    },
+    static get properties() {
+      return {
+        filePath: String,
+        _allFileActions: {
+          type: Array,
+          value: () => Object.values(GrEditConstants.Actions),
+        },
+        _fileActions: {
+          type: Array,
+          computed: '_computeFileActions(_allFileActions)',
+        },
+      };
+    }
 
     _handleActionTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this._dispatchFileAction(e.detail.id, this.filePath);
-    },
+    }
 
     _dispatchFileAction(action, path) {
       this.dispatchEvent(new CustomEvent(
           'file-action-tap',
           {detail: {action, path}, bubbles: true, composed: true}));
-    },
+    }
 
     _computeFileActions(actions) {
       // TODO(kaspern): conditionally disable some actions based on file status.
@@ -58,6 +61,8 @@
           id: action.id,
         };
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditFileControls.is, GrEditFileControls);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html
index 7979e57..dc26468 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-edit-file-controls/gr-edit-file-controls_test.html
@@ -17,7 +17,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-edit-file-controls</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
index bbcb90c..ab50921 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.js
@@ -24,9 +24,21 @@
 
   const STORAGE_DEBOUNCE_INTERVAL_MS = 100;
 
-  Polymer({
-    is: 'gr-editor-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.PathListMixin
+    */
+  class GrEditorView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.PathListBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-editor-view'; }
     /**
      * Fired when the title of the page should change.
      *
@@ -39,69 +51,69 @@
      * @event show-alert
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      _change: Object,
-      _changeEditDetail: Object,
-      _changeNum: String,
-      _patchNum: String,
-      _path: String,
-      _type: String,
-      _content: String,
-      _newContent: String,
-      _saving: {
-        type: Boolean,
-        value: false,
-      },
-      _successfulSave: {
-        type: Boolean,
-        value: false,
-      },
-      _saveDisabled: {
-        type: Boolean,
-        value: true,
-        computed: '_computeSaveDisabled(_content, _newContent, _saving)',
-      },
-      _prefs: Object,
-    },
+        _change: Object,
+        _changeEditDetail: Object,
+        _changeNum: String,
+        _patchNum: String,
+        _path: String,
+        _type: String,
+        _content: String,
+        _newContent: String,
+        _saving: {
+          type: Boolean,
+          value: false,
+        },
+        _successfulSave: {
+          type: Boolean,
+          value: false,
+        },
+        _saveDisabled: {
+          type: Boolean,
+          value: true,
+          computed: '_computeSaveDisabled(_content, _newContent, _saving)',
+        },
+        _prefs: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.PathListBehavior,
-    ],
+    get keyBindings() {
+      return {
+        'ctrl+s meta+s': '_handleSaveShortcut',
+      };
+    }
 
-    listeners: {
-      'content-change': '_handleContentChange',
-    },
-
-    keyBindings: {
-      'ctrl+s meta+s': '_handleSaveShortcut',
-    },
+    created() {
+      super.created();
+      this.addEventListener('content-change',
+          e => this._handleContentChange(e));
+    }
 
     attached() {
+      super.attached();
       this._getEditPrefs().then(prefs => { this._prefs = prefs; });
-    },
+    }
 
     get storageKey() {
       return `c${this._changeNum}_ps${this._patchNum}_${this._path}`;
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getEditPrefs() {
       return this.$.restAPI.getEditPreferences();
-    },
+    }
 
     _paramsChanged(value) {
       if (value.view !== Gerrit.Nav.View.EDIT) {
@@ -126,13 +138,13 @@
       promises.push(
           this._getFileData(this._changeNum, this._path, this._patchNum));
       return Promise.all(promises);
-    },
+    }
 
     _getChangeDetail(changeNum) {
       return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
         this._change = change;
       });
-    },
+    }
 
     _handlePathChanged(e) {
       const path = e.detail;
@@ -146,13 +158,13 @@
         this._successfulSave = true;
         this._viewEditInChangeView();
       });
-    },
+    }
 
     _viewEditInChangeView() {
       const patch = this._successfulSave ? this.EDIT_NAME : this._patchNum;
       Gerrit.Nav.navigateToChange(this._change, patch, null,
           patch !== this.EDIT_NAME);
-    },
+    }
 
     _getFileData(changeNum, path, patchNum) {
       const storedContent =
@@ -183,7 +195,7 @@
               this._type = '';
             }
           });
-    },
+    }
 
     _saveEdit() {
       this._saving = true;
@@ -198,7 +210,7 @@
         this._content = this._newContent;
         this._successfulSave = true;
       });
-    },
+    }
 
     _showAlert(message) {
       this.dispatchEvent(new CustomEvent('show-alert', {
@@ -206,7 +218,7 @@
         bubbles: true,
         composed: true,
       }));
-    },
+    }
 
     _computeSaveDisabled(content, newContent, saving) {
       // Polymer 2: check for undefined
@@ -222,12 +234,12 @@
         return true;
       }
       return content === newContent;
-    },
+    }
 
     _handleCloseTap() {
       // TODO(kaspern): Add a confirm dialog if there are unsaved changes.
       this._viewEditInChangeView();
-    },
+    }
 
     _handleContentChange(e) {
       this.debounce('store', () => {
@@ -239,13 +251,15 @@
           this.$.storage.eraseEditableContentItem(this.storageKey);
         }
       }, STORAGE_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _handleSaveShortcut(e) {
       e.preventDefault();
       if (!this._saveDisabled) {
         this._saveEdit();
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditorView.is, GrEditorView);
 })();
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html
index 226472f..ebd624e 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.html
@@ -17,7 +17,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-editor-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/gr-app-element.html b/polygerrit-ui/app/elements/gr-app-element.html
index ca60de4..f758280 100644
--- a/polygerrit-ui/app/elements/gr-app-element.html
+++ b/polygerrit-ui/app/elements/gr-app-element.html
@@ -75,6 +75,7 @@
         border-right: 0;
         border-left: 0;
         border-top: 0;
+        box-shadow: var(--header-box-shadow);
       }
       footer {
         background: var(--footer-background, var(--footer-background-color, #eee));
@@ -210,7 +211,6 @@
     </footer>
     <gr-overlay id="keyboardShortcuts" with-backdrop>
       <gr-keyboard-shortcuts-dialog
-          view="[[params.view]]"
           on-close="_handleKeyboardShortcutDialogClose"></gr-keyboard-shortcuts-dialog>
     </gr-overlay>
     <gr-overlay id="registrationOverlay" with-backdrop>
diff --git a/polygerrit-ui/app/elements/gr-app-element.js b/polygerrit-ui/app/elements/gr-app-element.js
index b8f789b..4ed0d3a 100644
--- a/polygerrit-ui/app/elements/gr-app-element.js
+++ b/polygerrit-ui/app/elements/gr-app-element.js
@@ -17,90 +17,90 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-app-element',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrAppElement extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-app-element'; }
     /**
      * Fired when the URL location changes.
      *
      * @event location-change
      */
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * @type {{ query: string, view: string, screen: string }}
        */
-      params: Object,
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
+        params: Object,
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
 
-      _account: {
-        type: Object,
-        observer: '_accountChanged',
-      },
+        _account: {
+          type: Object,
+          observer: '_accountChanged',
+        },
 
-      /**
+        /**
        * The last time the g key was pressed in milliseconds (or a keydown event
        * was handled if the key is held down).
        * @type {number|null}
        */
-      _lastGKeyPressTimestamp: {
-        type: Number,
-        value: null,
-      },
+        _lastGKeyPressTimestamp: {
+          type: Number,
+          value: null,
+        },
 
-      /**
+        /**
        * @type {{ plugin: Object }}
        */
-      _serverConfig: Object,
-      _version: String,
-      _showChangeListView: Boolean,
-      _showDashboardView: Boolean,
-      _showChangeView: Boolean,
-      _showDiffView: Boolean,
-      _showSettingsView: Boolean,
-      _showAdminView: Boolean,
-      _showCLAView: Boolean,
-      _showEditorView: Boolean,
-      _showPluginScreen: Boolean,
-      _showDocumentationSearch: Boolean,
-      /** @type {?} */
-      _viewState: Object,
-      /** @type {?} */
-      _lastError: Object,
-      _lastSearchPage: String,
-      _path: String,
-      _pluginScreenName: {
-        type: String,
-        computed: '_computePluginScreenName(params)',
-      },
-      _settingsUrl: String,
-      _feedbackUrl: String,
-      // Used to allow searching on mobile
-      mobileSearch: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _serverConfig: Object,
+        _version: String,
+        _showChangeListView: Boolean,
+        _showDashboardView: Boolean,
+        _showChangeView: Boolean,
+        _showDiffView: Boolean,
+        _showSettingsView: Boolean,
+        _showAdminView: Boolean,
+        _showCLAView: Boolean,
+        _showEditorView: Boolean,
+        _showPluginScreen: Boolean,
+        _showDocumentationSearch: Boolean,
+        /** @type {?} */
+        _viewState: Object,
+        /** @type {?} */
+        _lastError: Object,
+        _lastSearchPage: String,
+        _path: String,
+        _pluginScreenName: {
+          type: String,
+          computed: '_computePluginScreenName(params)',
+        },
+        _settingsUrl: String,
+        _feedbackUrl: String,
+        // Used to allow searching on mobile
+        mobileSearch: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    listeners: {
-      'page-error': '_handlePageError',
-      'title-change': '_handleTitleChange',
-      'location-change': '_handleLocationChange',
-      'rpc-log': '_handleRpcLog',
-    },
-
-    observers: [
-      '_viewChanged(params.view)',
-      '_paramsChanged(params.*)',
-    ],
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
+    static get observers() {
+      return [
+        '_viewChanged(params.view)',
+        '_paramsChanged(params.*)',
+      ];
+    }
 
     keyboardShortcuts() {
       return {
@@ -111,13 +111,23 @@
         [this.Shortcut.GO_TO_ABANDONED_CHANGES]: '_goToAbandonedChanges',
         [this.Shortcut.GO_TO_WATCHED_CHANGES]: '_goToWatchedChanges',
       };
-    },
+    }
 
     created() {
+      super.created();
       this._bindKeyboardShortcuts();
-    },
+      this.addEventListener('page-error',
+          e => this._handlePageError(e));
+      this.addEventListener('title-change',
+          e => this._handleTitleChange(e));
+      this.addEventListener('location-change',
+          e => this._handleLocationChange(e));
+      this.addEventListener('rpc-log',
+          e => this._handleRpcLog(e));
+    }
 
     ready() {
+      super.ready();
       this.$.reporting.appStarted();
       this.$.router.start();
 
@@ -165,7 +175,7 @@
           selectedChangeIndex: 0,
         },
       };
-    },
+    }
 
     _bindKeyboardShortcuts() {
       this.bindShortcut(this.Shortcut.SEND_REPLY,
@@ -287,7 +297,7 @@
 
       this.bindShortcut(
           this.Shortcut.SEARCH, '/');
-    },
+    }
 
     _accountChanged(account) {
       if (!account) { return; }
@@ -298,7 +308,7 @@
       this.$.restAPI.getEditPreferences();
       this.$.errorManager.knownAccountId =
           this._account && this._account._account_id || null;
-    },
+    }
 
     _viewChanged(view) {
       this.$.errorView.classList.remove('show');
@@ -328,7 +338,7 @@
         });
       }
       this.$.header.unfloat();
-    },
+    }
 
     _handlePageError(e) {
       const props = [
@@ -356,7 +366,7 @@
           this._lastError = err;
         });
       }
-    },
+    }
 
     _handleLocationChange(e) {
       const hash = e.detail.hash.substring(1);
@@ -365,7 +375,7 @@
         pathname += '@' + hash;
       }
       this.set('_path', pathname);
-    },
+    }
 
     _paramsChanged(paramsRecord) {
       const params = paramsRecord.base;
@@ -373,7 +383,7 @@
       if (viewsToCheck.includes(params.view)) {
         this.set('_lastSearchPage', location.pathname);
       }
-    },
+    }
 
     _handleTitleChange(e) {
       if (e.detail.title) {
@@ -381,54 +391,54 @@
       } else {
         document.title = '';
       }
-    },
+    }
 
     _showKeyboardShortcuts(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
       this.$.keyboardShortcuts.open();
-    },
+    }
 
     _handleKeyboardShortcutDialogClose() {
       this.$.keyboardShortcuts.close();
-    },
+    }
 
     _handleAccountDetailUpdate(e) {
       this.$.mainHeader.reload();
       if (this.params.view === Gerrit.Nav.View.SETTINGS) {
         this.$$('gr-settings-view').reloadAccountDetail();
       }
-    },
+    }
 
     _handleRegistrationDialogClose(e) {
       this.params.justRegistered = false;
       this.$.registrationOverlay.close();
-    },
+    }
 
     _goToOpenedChanges() {
       Gerrit.Nav.navigateToStatusSearch('open');
-    },
+    }
 
     _goToUserDashboard() {
       Gerrit.Nav.navigateToUserDashboard();
-    },
+    }
 
     _goToMergedChanges() {
       Gerrit.Nav.navigateToStatusSearch('merged');
-    },
+    }
 
     _goToAbandonedChanges() {
       Gerrit.Nav.navigateToStatusSearch('abandoned');
-    },
+    }
 
     _goToWatchedChanges() {
       // The query is hardcoded, and doesn't respect custom menu entries
       Gerrit.Nav.navigateToSearchQuery('is:watched is:open');
-    },
+    }
 
     _computePluginScreenName({plugin, screen}) {
       if (!plugin || !screen) return '';
       return `${plugin}-screen-${screen}`;
-    },
+    }
 
     _logWelcome() {
       console.group('Runtime Info');
@@ -441,7 +451,7 @@
         console.log(`Please file bugs and feedback at: ${this._feedbackUrl}`);
       }
       console.groupEnd();
-    },
+    }
 
     /**
      * Intercept RPC log events emitted by REST API interfaces.
@@ -451,17 +461,19 @@
     _handleRpcLog(e) {
       this.$.reporting.reportRpcTiming(e.detail.anonymizedUrl,
           e.detail.elapsed);
-    },
+    }
 
     _mobileSearchToggle(e) {
       this.mobileSearch = !this.mobileSearch;
-    },
+    }
 
     getThemeEndpoint() {
       // For now, we only have dark mode and light mode
       return window.localStorage.getItem('dark-theme') ?
         'app-theme-dark' :
         'app-theme-light';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAppElement.is, GrAppElement);
 })();
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index ac8ea1a..46a81ee 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -17,7 +17,11 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-app',
-  });
+  class GrApp extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-app'; }
+  }
+
+  customElements.define(GrApp.is, GrApp);
 })();
diff --git a/polygerrit-ui/app/elements/gr-app_test.html b/polygerrit-ui/app/elements/gr-app_test.html
index 9f1b7f8..c069f8b 100644
--- a/polygerrit-ui/app/elements/gr-app_test.html
+++ b/polygerrit-ui/app/elements/gr-app_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-app</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html
index 2537a37..10ba710 100644
--- a/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-admin-api/gr-admin-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-admin-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html
index 0c4149c..c95128b 100644
--- a/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-attribute-helper/gr-attribute-helper_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-attribute-helper</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html
index 9e657fa..a00dc68 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-dom-hooks</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
index ba49291..9942716 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator.js
@@ -19,33 +19,38 @@
 
   const INIT_PROPERTIES_TIMEOUT_MS = 10000;
 
-  Polymer({
-    is: 'gr-endpoint-decorator',
+  class GrEndpointDecorator extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-endpoint-decorator'; }
 
-    properties: {
-      name: String,
-      /** @type {!Map} */
-      _domHooks: {
-        type: Map,
-        value() { return new Map(); },
-      },
-      /**
+    static get properties() {
+      return {
+        name: String,
+        /** @type {!Map} */
+        _domHooks: {
+          type: Map,
+          value() { return new Map(); },
+        },
+        /**
        * This map prevents importing the same endpoint twice.
        * Without caching, if a plugin is loaded after the loaded plugins
        * callback fires, it will be imported twice and appear twice on the page.
        * @type {!Map}
        */
-      _initializedPlugins: {
-        type: Map,
-        value() { return new Map(); },
-      },
-    },
+        _initializedPlugins: {
+          type: Map,
+          value() { return new Map(); },
+        },
+      };
+    }
 
     detached() {
+      super.detached();
       for (const [el, domHook] of this._domHooks) {
         domHook.handleInstanceDetached(el);
       }
-    },
+    }
 
     /**
      * @suppress {checkTypes}
@@ -54,7 +59,7 @@
       return new Promise((resolve, reject) => {
         (this.importHref || Polymer.importHref)(url, resolve, reject);
       });
-    },
+    }
 
     _initDecoration(name, plugin) {
       const el = document.createElement(name);
@@ -62,7 +67,7 @@
           this.getContentChildren().find(
               el => el.nodeName !== 'GR-ENDPOINT-PARAM'))
           .then(el => this._appendChild(el));
-    },
+    }
 
     _initReplacement(name, plugin) {
       this.getContentChildNodes()
@@ -71,12 +76,12 @@
       const el = document.createElement(name);
       return this._initProperties(el, plugin).then(
           el => this._appendChild(el));
-    },
+    }
 
     _getEndpointParams() {
       return Array.from(
           Polymer.dom(this).querySelectorAll('gr-endpoint-param'));
-    },
+    }
 
     /**
      * @param {!Element} el
@@ -109,11 +114,11 @@
             clearTimeout(timeoutId);
             return el;
           });
-    },
+    }
 
     _appendChild(el) {
       return Polymer.dom(this.root).appendChild(el);
-    },
+    }
 
     _initModule({moduleName, plugin, type, domHook}) {
       const name = plugin.getPluginName() + '.' + moduleName;
@@ -137,9 +142,10 @@
         domHook.handleInstanceAttached(el);
         this._domHooks.set(el, domHook);
       });
-    },
+    }
 
     ready() {
+      super.ready();
       Gerrit._endpoints.onNewEndpoint(this.name, this._initModule.bind(this));
       Gerrit.awaitPluginsLoaded().then(() => Promise.all(
           Gerrit._endpoints.getPlugins(this.name).map(
@@ -149,6 +155,8 @@
             .getDetails(this.name)
             .forEach(this._initModule, this)
       );
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEndpointDecorator.is, GrEndpointDecorator);
 })();
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html
index b0ad585..58e2074 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-endpoint-decorator</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.js b/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.js
index c7a2d9a..3010750 100644
--- a/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.js
+++ b/polygerrit-ui/app/elements/plugins/gr-endpoint-param/gr-endpoint-param.js
@@ -17,17 +17,21 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-endpoint-param',
+  class GrEndpointParam extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-endpoint-param'; }
 
-    properties: {
-      name: String,
-      value: {
-        type: Object,
-        notify: true,
-        observer: '_valueChanged',
-      },
-    },
+    static get properties() {
+      return {
+        name: String,
+        value: {
+          type: Object,
+          notify: true,
+          observer: '_valueChanged',
+        },
+      };
+    }
 
     _valueChanged(newValue, oldValue) {
       /* In polymer 2 the following change was made:
@@ -42,6 +46,8 @@
         value: newValue,
       };
       this.dispatchEvent(new CustomEvent('value-changed', {detail}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEndpointParam.is, GrEndpointParam);
 })();
diff --git a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html
index bd76bd4..a98a0d2 100644
--- a/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-event-helper/gr-event-helper_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-event-helper</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
index e90ff30..aa9b13e 100644
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style.js
@@ -17,20 +17,24 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-external-style',
+  class GrExternalStyle extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-external-style'; }
 
-    properties: {
-      name: String,
-      _urlsImported: {
-        type: Array,
-        value() { return []; },
-      },
-      _stylesApplied: {
-        type: Array,
-        value() { return []; },
-      },
-    },
+    static get properties() {
+      return {
+        name: String,
+        _urlsImported: {
+          type: Array,
+          value() { return []; },
+        },
+        _stylesApplied: {
+          type: Array,
+          value() { return []; },
+        },
+      };
+    }
 
     /**
      * @suppress {checkTypes}
@@ -41,14 +45,13 @@
       return new Promise((resolve, reject) => {
         (this.importHref || Polymer.importHref)(url, resolve, reject);
       });
-    },
+    }
 
     _applyStyle(name) {
       if (this._stylesApplied.includes(name)) { return; }
       this._stylesApplied.push(name);
-      // Hybrid custom-style syntax:
-      // https://polymer-library.polymer-project.org/2.0/docs/devguide/style-shadow-dom
-      const s = document.createElement('style', 'custom-style');
+
+      const s = document.createElement('style');
       s.setAttribute('include', name);
       const cs = document.createElement('custom-style');
       cs.appendChild(s);
@@ -57,7 +60,7 @@
       const topEl = document.getElementsByTagName('body')[0];
       topEl.insertBefore(cs, topEl.firstChild);
       Polymer.updateStyles();
-    },
+    }
 
     _importAndApply() {
       Promise.all(Gerrit._endpoints.getPlugins(this.name).map(
@@ -68,14 +71,18 @@
           this._applyStyle(name);
         }
       });
-    },
+    }
 
     attached() {
+      super.attached();
       this._importAndApply();
-    },
+    }
 
     ready() {
+      super.ready();
       Gerrit.awaitPluginsLoaded().then(() => this._importAndApply());
-    },
-  });
+    }
+  }
+
+  customElements.define(GrExternalStyle.is, GrExternalStyle);
 })();
diff --git a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
index 9566067..9f0c950 100644
--- a/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-external-style/gr-external-style_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-external-style</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
index 21da106..30adcc8 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host.js
@@ -17,15 +17,19 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-plugin-host',
+  class GrPluginHost extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-plugin-host'; }
 
-    properties: {
-      config: {
-        type: Object,
-        observer: '_configChanged',
-      },
-    },
+    static get properties() {
+      return {
+        config: {
+          type: Object,
+          observer: '_configChanged',
+        },
+      };
+    }
 
     _configChanged(config) {
       const plugins = config.plugin;
@@ -50,7 +54,7 @@
       }
 
       Gerrit._loadPlugins(pluginsPending, pluginOpts);
-    },
+    }
 
     /**
      * Omit .js plugins that have .html counterparts.
@@ -61,6 +65,8 @@
         const counterpart = url.replace(/\.js$/, '.html');
         return !htmlPlugins.includes(counterpart);
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPluginHost.is, GrPluginHost);
 })();
diff --git a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
index 3a8e4d8..1f748b8 100644
--- a/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-plugin-host/gr-plugin-host_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-host</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.html b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.html
index 402d988..d084445 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.html
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.html
@@ -20,7 +20,9 @@
 
 <dom-module id="gr-plugin-popup">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <gr-overlay id="overlay" with-backdrop>
       <slot></slot>
     </gr-overlay>
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.js b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.js
index 2e7a2b7..412e788a 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.js
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup.js
@@ -17,19 +17,23 @@
 (function(window) {
   'use strict';
 
-  Polymer({
-    is: 'gr-plugin-popup',
+  class GrPluginPopup extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-plugin-popup'; }
 
     get opened() {
       return this.$.overlay.opened;
-    },
+    }
 
     open() {
       return this.$.overlay.open();
-    },
+    }
 
     close() {
       this.$.overlay.close();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPluginPopup.is, GrPluginPopup);
 })(window);
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html
index 1f1e81e..2ff2aba 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-plugin-popup_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-popup</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html
index 53370e2..0be07d4 100644
--- a/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-popup-interface/gr-popup-interface_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-popup-interface</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html
index 0b32f8a..5a47a85 100644
--- a/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-repo-api/gr-repo-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
index cbc2de6..6248d78 100644
--- a/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-settings-api/gr-settings-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html
index 16b7eb8..7d14e21 100644
--- a/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-styles-api/gr-styles-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-admin-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html
index 6332b91..9401a15 100644
--- a/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html
+++ b/polygerrit-ui/app/elements/plugins/gr-theme-api/gr-theme-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-theme-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
index 086cc7c..e685030 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.html
@@ -16,6 +16,7 @@
 -->
 
 <link rel="import" href="/bower_components/polymer/polymer.html">
+<link rel="import" href="/bower_components/iron-input/iron-input.html">
 
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../shared/gr-avatar/gr-avatar.html">
@@ -39,7 +40,9 @@
         display: none;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="gr-form-styles">
       <section>
         <span class="title"></span>
@@ -81,7 +84,6 @@
             hidden$="[[!usernameMutable]]"
             class="value">
           <iron-input
-              disabled="[[_saving]]"
               on-keydown="_handleKeydown"
               bind-value="{{_username}}">
             <input
@@ -102,7 +104,6 @@
             hidden$="[[!nameMutable]]"
             class="value">
           <iron-input
-              disabled="[[_saving]]"
               on-keydown="_handleKeydown"
               bind-value="{{_account.name}}">
             <input
@@ -118,7 +119,6 @@
         <span class="title">Status (e.g. "Vacation")</span>
         <span class="value">
           <iron-input
-              disabled="[[_saving]]"
               on-keydown="_handleKeydown"
               bind-value="{{_account.status}}">
             <input
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
index 3ba3a80..e509b8b 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.js
@@ -17,65 +17,71 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-account-info',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrAccountInfo extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-info'; }
     /**
      * Fired when account details are changed.
      *
      * @event account-detail-update
      */
 
-    properties: {
-      usernameMutable: {
-        type: Boolean,
-        notify: true,
-        computed: '_computeUsernameMutable(_serverConfig, _account.username)',
-      },
-      nameMutable: {
-        type: Boolean,
-        notify: true,
-        computed: '_computeNameMutable(_serverConfig)',
-      },
-      hasUnsavedChanges: {
-        type: Boolean,
-        notify: true,
-        computed: '_computeHasUnsavedChanges(_hasNameChange, ' +
+    static get properties() {
+      return {
+        usernameMutable: {
+          type: Boolean,
+          notify: true,
+          computed: '_computeUsernameMutable(_serverConfig, _account.username)',
+        },
+        nameMutable: {
+          type: Boolean,
+          notify: true,
+          computed: '_computeNameMutable(_serverConfig)',
+        },
+        hasUnsavedChanges: {
+          type: Boolean,
+          notify: true,
+          computed: '_computeHasUnsavedChanges(_hasNameChange, ' +
             '_hasUsernameChange, _hasStatusChange)',
-      },
+        },
 
-      _hasNameChange: Boolean,
-      _hasUsernameChange: Boolean,
-      _hasStatusChange: Boolean,
-      _loading: {
-        type: Boolean,
-        value: false,
-      },
-      _saving: {
-        type: Boolean,
-        value: false,
-      },
-      /** @type {?} */
-      _account: Object,
-      _serverConfig: Object,
-      _username: {
-        type: String,
-        observer: '_usernameChanged',
-      },
-      _avatarChangeUrl: {
-        type: String,
-        value: '',
-      },
-    },
+        _hasNameChange: Boolean,
+        _hasUsernameChange: Boolean,
+        _hasStatusChange: Boolean,
+        _loading: {
+          type: Boolean,
+          value: false,
+        },
+        _saving: {
+          type: Boolean,
+          value: false,
+        },
+        /** @type {?} */
+        _account: Object,
+        _serverConfig: Object,
+        _username: {
+          type: String,
+          observer: '_usernameChanged',
+        },
+        _avatarChangeUrl: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_nameChanged(_account.name)',
-      '_statusChanged(_account.status)',
-    ],
+    static get observers() {
+      return [
+        '_nameChanged(_account.name)',
+        '_statusChanged(_account.status)',
+      ];
+    }
 
     loadData() {
       const promises = [];
@@ -104,7 +110,7 @@
       return Promise.all(promises).then(() => {
         this._loading = false;
       });
-    },
+    }
 
     save() {
       if (!this.hasUnsavedChanges) {
@@ -123,29 +129,29 @@
             this._saving = false;
             this.fire('account-detail-update');
           });
-    },
+    }
 
     _maybeSetName() {
       return this._hasNameChange && this.nameMutable ?
         this.$.restAPI.setAccountName(this._account.name) :
         Promise.resolve();
-    },
+    }
 
     _maybeSetUsername() {
       return this._hasUsernameChange && this.usernameMutable ?
         this.$.restAPI.setAccountUsername(this._username) :
         Promise.resolve();
-    },
+    }
 
     _maybeSetStatus() {
       return this._hasStatusChange ?
         this.$.restAPI.setAccountStatus(this._account.status) :
         Promise.resolve();
-    },
+    }
 
     _computeHasUnsavedChanges(nameChanged, usernameChanged, statusChanged) {
       return nameChanged || usernameChanged || statusChanged;
-    },
+    }
 
     _computeUsernameMutable(config, username) {
       // Polymer 2: check for undefined
@@ -159,34 +165,34 @@
       // Username may not be changed once it is set.
       return config.auth.editable_account_fields.includes('USER_NAME') &&
           !username;
-    },
+    }
 
     _computeNameMutable(config) {
       return config.auth.editable_account_fields.includes('FULL_NAME');
-    },
+    }
 
     _statusChanged() {
       if (this._loading) { return; }
       this._hasStatusChange = true;
-    },
+    }
 
     _usernameChanged() {
       if (this._loading || !this._account) { return; }
       this._hasUsernameChange =
           (this._account.username || '') !== (this._username || '');
-    },
+    }
 
     _nameChanged() {
       if (this._loading) { return; }
       this._hasNameChange = true;
-    },
+    }
 
     _handleKeydown(e) {
       if (e.keyCode === 13) { // Enter
         e.stopPropagation();
         this.save();
       }
-    },
+    }
 
     _hideAvatarChangeUrl(avatarChangeUrl) {
       if (!avatarChangeUrl) {
@@ -194,6 +200,8 @@
       }
 
       return '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountInfo.is, GrAccountInfo);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
index a35c1f0..a9056b91 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-info</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html
index 852161c..74d92d3 100644
--- a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.html
@@ -32,7 +32,9 @@
         width: auto;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="gr-form-styles">
       <table id="agreements">
         <thead>
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js
index 41595a98..13992f8 100644
--- a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list.js
@@ -17,33 +17,41 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-agreements-list',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    */
+  class GrAgreementsList extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-agreements-list'; }
 
-    properties: {
-      _agreements: Array,
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-    ],
+    static get properties() {
+      return {
+        _agreements: Array,
+      };
+    }
 
     attached() {
+      super.attached();
       this.loadData();
-    },
+    }
 
     loadData() {
       return this.$.restAPI.getAccountAgreements().then(agreements => {
         this._agreements = agreements;
       });
-    },
+    }
 
     getUrl() {
       return this.getBaseUrl() + '/settings/new-agreement';
-    },
+    }
 
     getUrlBase(item) {
       return this.getBaseUrl() + '/' + item;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAgreementsList.is, GrAgreementsList);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
index 14cf97c..cd5bc09 100644
--- a/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-agreements-list/gr-agreements-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.html b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.html
index 88a53ee..09a9dbc 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.html
@@ -24,7 +24,9 @@
 
 <dom-module id="gr-change-table-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       #changeCols {
         width: auto;
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.js b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.js
index 85eed9c..d92c148 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.js
@@ -17,23 +17,28 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-change-table-editor',
+  /**
+    * @appliesMixin Gerrit.ChangeTableMixin
+    */
+  class GrChangeTableEditor extends Polymer.mixinBehaviors( [
+    Gerrit.ChangeTableBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-table-editor'; }
 
-    properties: {
-      displayedColumns: {
-        type: Array,
-        notify: true,
-      },
-      showNumber: {
-        type: Boolean,
-        notify: true,
-      },
-    },
-
-    behaviors: [
-      Gerrit.ChangeTableBehavior,
-    ],
+    static get properties() {
+      return {
+        displayedColumns: {
+          type: Array,
+          notify: true,
+        },
+        showNumber: {
+          type: Boolean,
+          notify: true,
+        },
+      };
+    }
 
     /**
      * Get the list of enabled column names from whichever checkboxes are
@@ -45,7 +50,7 @@
           .querySelectorAll('.checkboxContainer input:not([name=number])'))
           .filter(checkbox => checkbox.checked)
           .map(checkbox => checkbox.name);
-    },
+    }
 
     /**
      * Handle a click on a checkbox container and relay the click to the checkbox it
@@ -55,7 +60,7 @@
       const checkbox = Polymer.dom(e.target).querySelector('input');
       if (!checkbox) { return; }
       checkbox.click();
-    },
+    }
 
     /**
      * Handle a click on the number checkbox and update the showNumber property
@@ -63,7 +68,7 @@
      */
     _handleNumberCheckboxClick(e) {
       this.showNumber = Polymer.dom(e).rootTarget.checked;
-    },
+    }
 
     /**
      * Handle a click on a displayed column checkboxes (excluding number) and
@@ -71,6 +76,8 @@
      */
     _handleTargetClick(e) {
       this.set('displayedColumns', this._getDisplayedColumns());
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeTableEditor.is, GrChangeTableEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
index 29a7081..ec37c03 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.html b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.html
index 76f21f0..fb5ab15 100644
--- a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.html
@@ -66,7 +66,9 @@
         max-width: 50em;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <main>
       <h1>New Contributor Agreement</h1>
       <h3>Select an agreement type:</h3>
diff --git a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.js b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.js
index 41a9800..98f1413 100644
--- a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view.js
@@ -17,33 +17,40 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-cla-view',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrClaView extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-cla-view'; }
 
-    properties: {
-      _groups: Object,
-      /** @type {?} */
-      _serverConfig: Object,
-      _agreementsText: String,
-      _agreementName: String,
-      _signedAgreements: Array,
-      _showAgreements: {
-        type: Boolean,
-        value: false,
-      },
-      _agreementsUrl: String,
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        _groups: Object,
+        /** @type {?} */
+        _serverConfig: Object,
+        _agreementsText: String,
+        _agreementName: String,
+        _signedAgreements: Array,
+        _showAgreements: {
+          type: Boolean,
+          value: false,
+        },
+        _agreementsUrl: String,
+      };
+    }
 
     attached() {
+      super.attached();
       this.loadData();
 
       this.fire('title-change', {title: 'New Contributor Agreement'});
-    },
+    }
 
     loadData() {
       const promises = [];
@@ -62,7 +69,7 @@
       }));
 
       return Promise.all(promises);
-    },
+    }
 
     _getAgreementsUrl(configUrl) {
       let url;
@@ -76,14 +83,14 @@
       }
 
       return url;
-    },
+    }
 
     _handleShowAgreement(e) {
       this._agreementName = e.target.getAttribute('data-name');
       this._agreementsUrl =
           this._getAgreementsUrl(e.target.getAttribute('data-url'));
       this._showAgreements = true;
-    },
+    }
 
     _handleSaveAgreements(e) {
       this._createToast('Agreement saving...');
@@ -99,16 +106,16 @@
         this._agreementsText = '';
         this._showAgreements = false;
       });
-    },
+    }
 
     _createToast(message) {
       this.dispatchEvent(new CustomEvent(
           'show-alert', {detail: {message}, bubbles: true, composed: true}));
-    },
+    }
 
     _computeShowAgreementsClass(agreements) {
       return agreements ? 'show' : '';
-    },
+    }
 
     _disableAggreements(item, groups, signedAgreements) {
       for (const group of groups) {
@@ -119,16 +126,16 @@
         }
       }
       return false;
-    },
+    }
 
     _hideAggreements(item, groups, signedAgreements) {
       return this._disableAggreements(item, groups, signedAgreements) ?
         '' : 'hide';
-    },
+    }
 
     _disableAgreementsText(text) {
       return text.toLowerCase() === 'i agree' ? false : true;
-    },
+    }
 
     // This checks for auto_verify_group,
     // if specified it returns 'hideAgreementsTextBox' which
@@ -148,6 +155,8 @@
           }
         }
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrClaView.is, GrClaView);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html
index 53d6be1..833fa39 100644
--- a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-cla-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
index 53a30c3..80440c7 100644
--- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
+++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.html
@@ -24,8 +24,12 @@
 
 <dom-module id="gr-edit-preferences">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-form-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div id="editPreferences" class="gr-form-styles">
       <section>
         <span class="title">Tab width</span>
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.js b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.js
index 86350f9..36e53b0 100644
--- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.js
+++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences.js
@@ -17,66 +17,72 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-edit-preferences',
+  class GrEditPreferences extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-edit-preferences'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
 
-      /** @type {?} */
-      editPrefs: Object,
-    },
+        /** @type {?} */
+        editPrefs: Object,
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getEditPreferences().then(prefs => {
         this.editPrefs = prefs;
       });
-    },
+    }
 
     _handleEditPrefsChanged() {
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleEditSyntaxHighlightingChanged() {
       this.set('editPrefs.syntax_highlighting',
           this.$.editSyntaxHighlighting.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     _handleEditShowTabsChanged() {
       this.set('editPrefs.show_tabs', this.$.editShowTabs.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     _handleMatchBracketsChanged() {
       this.set('editPrefs.match_brackets', this.$.showMatchBrackets.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     _handleEditLineWrappingChanged() {
       this.set('editPrefs.line_wrapping', this.$.editShowLineWrapping.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     _handleIndentWithTabsChanged() {
       this.set('editPrefs.indent_with_tabs', this.$.showIndentWithTabs.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     _handleAutoCloseBracketsChanged() {
       this.set('editPrefs.auto_close_brackets',
           this.$.showAutoCloseBrackets.checked);
       this._handleEditPrefsChanged();
-    },
+    }
 
     save() {
       return this.$.restAPI.saveEditPreferences(this.editPrefs).then(res => {
         this.hasUnsavedChanges = false;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditPreferences.is, GrEditPreferences);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html
index c1c5c52..8b0bf86 100644
--- a/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-edit-preferences/gr-edit-preferences_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-edit-preferences</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.html b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.html
index caaf18b..041b2a7 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.html
@@ -23,7 +23,9 @@
 
 <dom-module id="gr-email-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       th {
         color: var(--deemphasized-text-color);
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.js b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.js
index 8490b26..8ec1067 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor.js
@@ -17,33 +17,37 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-email-editor',
+  class GrEmailEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-email-editor'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
 
-      _emails: Array,
-      _emailsToRemove: {
-        type: Array,
-        value() { return []; },
-      },
-      /** @type {?string} */
-      _newPreferred: {
-        type: String,
-        value: null,
-      },
-    },
+        _emails: Array,
+        _emailsToRemove: {
+          type: Array,
+          value() { return []; },
+        },
+        /** @type {?string} */
+        _newPreferred: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getAccountEmails().then(emails => {
         this._emails = emails;
       });
-    },
+    }
 
     save() {
       const promises = [];
@@ -62,7 +66,7 @@
         this._newPreferred = null;
         this.hasUnsavedChanges = false;
       });
-    },
+    }
 
     _handleDeleteButton(e) {
       const index = parseInt(Polymer.dom(e).localTarget
@@ -71,13 +75,13 @@
       this.push('_emailsToRemove', email);
       this.splice('_emails', index, 1);
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handlePreferredControlClick(e) {
       if (e.target.classList.contains('preferredControl')) {
         e.target.firstElementChild.click();
       }
-    },
+    }
 
     _handlePreferredChange(e) {
       const preferred = e.target.value;
@@ -90,6 +94,8 @@
           this.set(['_emails', i, 'preferred'], false);
         }
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEmailEditor.is, GrEmailEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html
index 8d3f2d2..e55ac97 100644
--- a/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-email-editor/gr-email-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-email-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.html b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.html
index cf73d99..7b8a191 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.html
@@ -26,7 +26,9 @@
 
 <dom-module id="gr-gpg-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       .keyHeader {
         width: 9em;
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.js b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.js
index 890061e..14d7a4c 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.js
@@ -17,27 +17,31 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-gpg-editor',
+  class GrGpgEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-gpg-editor'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        value: false,
-        notify: true,
-      },
-      _keys: Array,
-      /** @type {?} */
-      _keyToView: Object,
-      _newKey: {
-        type: String,
-        value: '',
-      },
-      _keysToRemove: {
-        type: Array,
-        value() { return []; },
-      },
-    },
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          value: false,
+          notify: true,
+        },
+        _keys: Array,
+        /** @type {?} */
+        _keyToView: Object,
+        _newKey: {
+          type: String,
+          value: '',
+        },
+        _keysToRemove: {
+          type: Array,
+          value() { return []; },
+        },
+      };
+    }
 
     loadData() {
       this._keys = [];
@@ -52,7 +56,7 @@
               return gpgKey;
             });
       });
-    },
+    }
 
     save() {
       const promises = this._keysToRemove.map(key => {
@@ -63,18 +67,18 @@
         this._keysToRemove = [];
         this.hasUnsavedChanges = false;
       });
-    },
+    }
 
     _showKey(e) {
       const el = Polymer.dom(e).localTarget;
       const index = parseInt(el.getAttribute('data-index'), 10);
       this._keyToView = this._keys[index];
       this.$.viewKeyOverlay.open();
-    },
+    }
 
     _closeOverlay() {
       this.$.viewKeyOverlay.close();
-    },
+    }
 
     _handleDeleteKey(e) {
       const el = Polymer.dom(e).localTarget;
@@ -82,7 +86,7 @@
       this.push('_keysToRemove', this._keys[index]);
       this.splice('_keys', index, 1);
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleAddKey() {
       this.$.addButton.disabled = true;
@@ -96,10 +100,12 @@
             this.$.addButton.disabled = false;
             this.$.newKey.disabled = false;
           });
-    },
+    }
 
     _computeAddButtonDisabled(newKey) {
       return !newKey.length;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrGpgEditor.is, GrGpgEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html
index 9cfbde5f..575285b 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-gpg-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.html b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.html
index ca500c8..e51294d 100644
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.html
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.html
@@ -23,7 +23,9 @@
 
 <dom-module id="gr-group-list">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
         #groups .nameColumn {
           min-width: 11em;
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.js b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.js
index d62a241..87fb852 100644
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.js
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list.js
@@ -17,12 +17,16 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-group-list',
+  class GrGroupList extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-group-list'; }
 
-    properties: {
-      _groups: Array,
-    },
+    static get properties() {
+      return {
+        _groups: Array,
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getAccountGroups().then(groups => {
@@ -30,11 +34,11 @@
           return a.name.localeCompare(b.name);
         });
       });
-    },
+    }
 
     _computeVisibleToAll(group) {
       return group.options.visible_to_all ? 'Yes' : 'No';
-    },
+    }
 
     _computeGroupPath(group) {
       if (!group || !group.id) { return; }
@@ -42,6 +46,8 @@
       // Group ID is already encoded from the API
       // Decode it here to match with our router encoding behavior
       return Gerrit.Nav.getUrlForGroup(decodeURIComponent(group.id));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrGroupList.is, GrGroupList);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html
index 3c3ece3..d8bf888 100644
--- a/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-group-list/gr-group-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
index faffbc5..22ba457 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.html
@@ -18,6 +18,7 @@
 <link rel="import" href="/bower_components/polymer/polymer.html">
 <link rel="import" href="../../../styles/gr-form-styles.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-copy-clipboard/gr-copy-clipboard.html">
 <link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
 <link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 <link rel="import" href="../../../styles/shared-styles.html">
@@ -37,6 +38,9 @@
       #generatedPasswordDisplay {
         margin: var(--spacing-l) 0;
       }
+      #generatedPasswordDisplay .title {
+        width: unset;
+      }
       #generatedPasswordDisplay .value {
         font-family: var(--monospace-font-family);
         font-size: var(--font-size-mono);
@@ -52,7 +56,9 @@
         right: 2em;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="gr-form-styles">
       <div hidden$="[[_passwordUrl]]">
         <section>
@@ -77,6 +83,12 @@
         <section id="generatedPasswordDisplay">
           <span class="title">New Password:</span>
           <span class="value">[[_generatedPassword]]</span>
+          <gr-copy-clipboard
+              has-tooltip
+              button-title="Copy password to clipboard"
+              hide-input
+              text="[[_generatedPassword]]">
+          </gr-copy-clipboard>
         </section>
         <section id="passwordWarning">
           This password will not be displayed again.<br>
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
index 003e471..5c0a059 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password.js
@@ -17,18 +17,23 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-http-password',
+  class GrHttpPassword extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-http-password'; }
 
-    properties: {
-      _username: String,
-      _generatedPassword: String,
-      _passwordUrl: String,
-    },
+    static get properties() {
+      return {
+        _username: String,
+        _generatedPassword: String,
+        _passwordUrl: String,
+      };
+    }
 
     attached() {
+      super.attached();
       this.loadData();
-    },
+    }
 
     loadData() {
       const promises = [];
@@ -42,7 +47,7 @@
       }));
 
       return Promise.all(promises);
-    },
+    }
 
     _handleGenerateTap() {
       this._generatedPassword = 'Generating...';
@@ -50,14 +55,16 @@
       this.$.restAPI.generateAccountHttpPassword().then(newPassword => {
         this._generatedPassword = newPassword;
       });
-    },
+    }
 
     _closeOverlay() {
       this.$.generatedPasswordOverlay.close();
-    },
+    }
 
     _generatedPasswordOverlayClosed() {
       this._generatedPassword = '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrHttpPassword.is, GrHttpPassword);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
index 8924058..89da766 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.html b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.html
index ee855cc..53d74f2 100644
--- a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.html
+++ b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.html
@@ -26,7 +26,9 @@
 
 <dom-module id="gr-identities">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       tr th.emailAddressHeader,
       tr th.identityHeader {
diff --git a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.js b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.js
index c927f1e..94c9e5a 100644
--- a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.js
+++ b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities.js
@@ -22,61 +22,66 @@
     'OAUTH',
   ];
 
-  Polymer({
-    is: 'gr-identities',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    */
+  class GrIdentities extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-identities'; }
 
-    properties: {
-      _identities: Object,
-      _idName: String,
-      serverConfig: Object,
-      _showLinkAnotherIdentity: {
-        type: Boolean,
-        computed: '_computeShowLinkAnotherIdentity(serverConfig)',
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-    ],
+    static get properties() {
+      return {
+        _identities: Object,
+        _idName: String,
+        serverConfig: Object,
+        _showLinkAnotherIdentity: {
+          type: Boolean,
+          computed: '_computeShowLinkAnotherIdentity(serverConfig)',
+        },
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getExternalIds().then(id => {
         this._identities = id;
       });
-    },
+    }
 
     _computeIdentity(id) {
       return id && id.startsWith('mailto:') ? '' : id;
-    },
+    }
 
     _computeHideDeleteClass(canDelete) {
       return canDelete ? 'show' : '';
-    },
+    }
 
     _handleDeleteItemConfirm() {
       this.$.overlay.close();
       return this.$.restAPI.deleteAccountIdentity([this._idName])
           .then(() => { this.loadData(); });
-    },
+    }
 
     _handleConfirmDialogCancel() {
       this.$.overlay.close();
-    },
+    }
 
     _handleDeleteItem(e) {
       const name = e.model.get('item.identity');
       if (!name) { return; }
       this._idName = name;
       this.$.overlay.open();
-    },
+    }
 
     _computeIsTrusted(item) {
       return item ? '' : 'Untrusted';
-    },
+    }
 
     filterIdentities(item) {
       return !item.identity.startsWith('username:');
-    },
+    }
 
     _computeShowLinkAnotherIdentity(config) {
       if (config && config.auth &&
@@ -86,7 +91,7 @@
       }
 
       return false;
-    },
+    }
 
     _computeLinkAnotherIdentity() {
       const baseUrl = this.getBaseUrl() || '';
@@ -95,6 +100,8 @@
         pathname = '/' + pathname.substring(baseUrl.length);
       }
       return baseUrl + '/login/' + encodeURIComponent(pathname) + '?link';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrIdentities.is, GrIdentities);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html
index 1277424..e2f8cad 100644
--- a/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-identities/gr-identities_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-identities</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.html b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.html
index df44c52..46fc165 100644
--- a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.html
@@ -44,7 +44,9 @@
         min-width: 23em;
       }
     </style>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="gr-form-styles">
       <table>
         <thead>
@@ -61,21 +63,21 @@
               <td class="buttonColumn">
                 <gr-button
                     link
-                    data-index="[[index]]"
+                    data-index$="[[index]]"
                     on-click="_handleMoveUpButton"
                     class="moveUpButton">↑</gr-button>
               </td>
               <td class="buttonColumn">
                 <gr-button
                     link
-                    data-index="[[index]]"
+                    data-index$="[[index]]"
                     on-click="_handleMoveDownButton"
                     class="moveDownButton">↓</gr-button>
               </td>
               <td>
                 <gr-button
                     link
-                    data-index="[[index]]"
+                    data-index$="[[index]]"
                     on-click="_handleDeleteButton"
                     class="remove-button">Delete</gr-button>
               </td>
diff --git a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.js b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.js
index aa83bf7..5b6c978 100644
--- a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor.js
@@ -17,35 +17,39 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-menu-editor',
+  class GrMenuEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-menu-editor'; }
 
-    properties: {
-      menuItems: Array,
-      _newName: String,
-      _newUrl: String,
-    },
+    static get properties() {
+      return {
+        menuItems: Array,
+        _newName: String,
+        _newUrl: String,
+      };
+    }
 
     _handleMoveUpButton(e) {
-      const index = Polymer.dom(e).localTarget.dataIndex;
+      const index = Number(Polymer.dom(e).localTarget.dataset.index);
       if (index === 0) { return; }
       const row = this.menuItems[index];
       const prev = this.menuItems[index - 1];
       this.splice('menuItems', index - 1, 2, row, prev);
-    },
+    }
 
     _handleMoveDownButton(e) {
-      const index = Polymer.dom(e).localTarget.dataIndex;
+      const index = Number(Polymer.dom(e).localTarget.dataset.index);
       if (index === this.menuItems.length - 1) { return; }
       const row = this.menuItems[index];
       const next = this.menuItems[index + 1];
       this.splice('menuItems', index, 2, next, row);
-    },
+    }
 
     _handleDeleteButton(e) {
-      const index = Polymer.dom(e).localTarget.dataIndex;
+      const index = Number(Polymer.dom(e).localTarget.dataset.index);
       this.splice('menuItems', index, 1);
-    },
+    }
 
     _handleAddButton() {
       if (this._computeAddDisabled(this._newName, this._newUrl)) { return; }
@@ -58,17 +62,19 @@
 
       this._newName = '';
       this._newUrl = '';
-    },
+    }
 
     _computeAddDisabled(newName, newUrl) {
       return !newName.length || !newUrl.length;
-    },
+    }
 
     _handleInputKeydown(e) {
       if (e.keyCode === 13) {
         e.stopPropagation();
         this._handleAddButton();
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrMenuEditor.is, GrMenuEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html
index 134e018..380e00a 100644
--- a/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-menu-editor/gr-menu-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html
index f366d2a..c289a49 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.html
@@ -26,7 +26,9 @@
 
 <dom-module id="gr-registration-dialog">
   <template>
-    <style include="gr-form-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       :host {
         display: block;
@@ -84,8 +86,7 @@
         <section>
           <div class="title">Full Name</div>
           <iron-input
-              bind-value="{{_account.name}}"
-              disabled="[[_saving]]">
+              bind-value="{{_account.name}}">
             <input
                 is="iron-input"
                 id="name"
@@ -96,8 +97,7 @@
         <section class$="[[_computeUsernameClass(_usernameMutable)]]">
           <div class="title">Username</div>
           <iron-input
-              bind-value="{{_account.username}}"
-              disabled="[[_saving]]">
+              bind-value="{{_account.username}}">
             <input
                 is="iron-input"
                 id="username"
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
index 0633416..af23f5b 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.js
@@ -17,9 +17,15 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-registration-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrRegistrationDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-registration-dialog'; }
     /**
      * Fired when account details are changed.
      *
@@ -32,40 +38,39 @@
      * @event close
      */
 
-    properties: {
-      settingsUrl: String,
-      /** @type {?} */
-      _account: {
-        type: Object,
-        value: () => {
+    static get properties() {
+      return {
+        settingsUrl: String,
+        /** @type {?} */
+        _account: {
+          type: Object,
+          value: () => {
           // Prepopulate possibly undefined fields with values to trigger
           // computed bindings.
-          return {email: null, name: null, username: null};
+            return {email: null, name: null, username: null};
+          },
         },
-      },
-      _usernameMutable: {
-        type: Boolean,
-        computed: '_computeUsernameMutable(_serverConfig, _account.username)',
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-        observer: '_loadingChanged',
-      },
-      _saving: {
-        type: Boolean,
-        value: false,
-      },
-      _serverConfig: Object,
-    },
+        _usernameMutable: {
+          type: Boolean,
+          computed: '_computeUsernameMutable(_serverConfig, _account.username)',
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+          observer: '_loadingChanged',
+        },
+        _saving: {
+          type: Boolean,
+          value: false,
+        },
+        _serverConfig: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    hostAttributes: {
-      role: 'dialog',
-    },
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'dialog');
+    }
 
     loadData() {
       this._loading = true;
@@ -84,7 +89,7 @@
       return Promise.all([loadAccount, loadConfig]).then(() => {
         this._loading = false;
       });
-    },
+    }
 
     _save() {
       this._saving = true;
@@ -101,26 +106,26 @@
         this._saving = false;
         this.fire('account-detail-update');
       });
-    },
+    }
 
     _handleSave(e) {
       e.preventDefault();
       this._save().then(this.close.bind(this));
-    },
+    }
 
     _handleClose(e) {
       e.preventDefault();
       this.close();
-    },
+    }
 
     close() {
       this._saving = true; // disable buttons indefinitely
       this.fire('close');
-    },
+    }
 
     _computeSaveDisabled(name, email, saving) {
       return !name || !email || saving;
-    },
+    }
 
     _computeUsernameMutable(config, username) {
       // Polymer 2: check for undefined
@@ -133,14 +138,16 @@
 
       return config.auth.editable_account_fields.includes('USER_NAME') &&
           !username;
-    },
+    }
 
     _computeUsernameClass(usernameMutable) {
       return usernameMutable ? '' : 'hide';
-    },
+    }
 
     _loadingChanged() {
       this.classList.toggle('loading', this._loading);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRegistrationDialog.is, GrRegistrationDialog);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
index d1b5c80..a987a26 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-registration-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js
index dae3b68..9702280 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item.js
@@ -17,12 +17,18 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-settings-item',
+  class GrSettingsItem extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-settings-item'; }
 
-    properties: {
-      anchor: String,
-      title: String,
-    },
-  });
+    static get properties() {
+      return {
+        anchor: String,
+        title: String,
+      };
+    }
+  }
+
+  customElements.define(GrSettingsItem.is, GrSettingsItem);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html
index 846f776..c356e80 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.html
@@ -20,8 +20,12 @@
 
 <dom-module id="gr-settings-menu-item">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-page-nav-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-page-nav-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="navStyles">
       <li><a href$="[[href]]">[[title]]</a></li>
     </div>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js
index 5db0031..e08e3d8 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-menu-item.js
@@ -17,12 +17,18 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-settings-menu-item',
+  class GrSettingsMenuItem extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-settings-menu-item'; }
 
-    properties: {
-      href: String,
-      title: String,
-    },
-  });
+    static get properties() {
+      return {
+        href: String,
+        title: String,
+      };
+    }
+  }
+
+  customElements.define(GrSettingsMenuItem.is, GrSettingsMenuItem);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
index 74971cf..e71aef5 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
@@ -74,9 +74,15 @@
         margin-right: var(--spacing-l);
       }
     </style>
-    <style include="gr-form-styles"></style>
-    <style include="gr-menu-page-styles"></style>
-    <style include="gr-page-nav-styles"></style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-menu-page-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-page-nav-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div class="loading" hidden$="[[!_loading]]">Loading...</div>
     <div hidden$="[[_loading]]" hidden>
       <gr-page-nav class="navStyles">
@@ -131,7 +137,6 @@
         <fieldset id="profile">
           <gr-account-info
               id="accountInfo"
-              mutable="{{_accountNameMutable}}"
               has-unsaved-changes="{{_accountInfoChanged}}"></gr-account-info>
           <gr-button
               on-click="_handleSaveAccountInfo"
@@ -373,7 +378,6 @@
                   class="newEmailInput"
                   bind-value="{{_newEmail}}"
                   type="text"
-                  disabled="[[_addingEmail]]"
                   on-keydown="_handleNewEmailKeydown"
                   placeholder="email@example.com">
                 <input
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index 714faab..39ca220 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -45,9 +45,19 @@
     'HTTP_LDAP',
   ];
 
-  Polymer({
-    is: 'gr-settings-view',
-
+  /**
+    * @appliesMixin Gerrit.DocsUrlMixin
+    * @appliesMixin Gerrit.ChangeTableMixin
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrSettingsView extends Polymer.mixinBehaviors( [
+    Gerrit.DocsUrlBehavior,
+    Gerrit.ChangeTableBehavior,
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-settings-view'; }
     /**
      * Fired when the title of the page should change.
      *
@@ -60,104 +70,102 @@
      * @event show-alert
      */
 
-    properties: {
-      prefs: {
-        type: Object,
-        value() { return {}; },
-      },
-      params: {
-        type: Object,
-        value() { return {}; },
-      },
-      _accountNameMutable: Boolean,
-      _accountInfoChanged: Boolean,
-      _changeTableColumnsNotDisplayed: Array,
-      /** @type {?} */
-      _localPrefs: {
-        type: Object,
-        value() { return {}; },
-      },
-      _localChangeTableColumns: {
-        type: Array,
-        value() { return []; },
-      },
-      _localMenu: {
-        type: Array,
-        value() { return []; },
-      },
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
-      _changeTableChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _prefsChanged: {
-        type: Boolean,
-        value: false,
-      },
-      /** @type {?} */
-      _diffPrefsChanged: Boolean,
-      /** @type {?} */
-      _editPrefsChanged: Boolean,
-      _menuChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _watchedProjectsChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _keysChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _gpgKeysChanged: {
-        type: Boolean,
-        value: false,
-      },
-      _newEmail: String,
-      _addingEmail: {
-        type: Boolean,
-        value: false,
-      },
-      _lastSentVerificationEmail: {
-        type: String,
-        value: null,
-      },
-      /** @type {?} */
-      _serverConfig: Object,
-      /** @type {?string} */
-      _docsBaseUrl: String,
-      _emailsChanged: Boolean,
+    static get properties() {
+      return {
+        prefs: {
+          type: Object,
+          value() { return {}; },
+        },
+        params: {
+          type: Object,
+          value() { return {}; },
+        },
+        _accountInfoChanged: Boolean,
+        _changeTableColumnsNotDisplayed: Array,
+        /** @type {?} */
+        _localPrefs: {
+          type: Object,
+          value() { return {}; },
+        },
+        _localChangeTableColumns: {
+          type: Array,
+          value() { return []; },
+        },
+        _localMenu: {
+          type: Array,
+          value() { return []; },
+        },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
+        _changeTableChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _prefsChanged: {
+          type: Boolean,
+          value: false,
+        },
+        /** @type {?} */
+        _diffPrefsChanged: Boolean,
+        /** @type {?} */
+        _editPrefsChanged: Boolean,
+        _menuChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _watchedProjectsChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _keysChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _gpgKeysChanged: {
+          type: Boolean,
+          value: false,
+        },
+        _newEmail: String,
+        _addingEmail: {
+          type: Boolean,
+          value: false,
+        },
+        _lastSentVerificationEmail: {
+          type: String,
+          value: null,
+        },
+        /** @type {?} */
+        _serverConfig: Object,
+        /** @type {?string} */
+        _docsBaseUrl: String,
+        _emailsChanged: Boolean,
 
-      /**
+        /**
        * For testing purposes.
        */
-      _loadingPromise: Object,
+        _loadingPromise: Object,
 
-      _showNumber: Boolean,
+        _showNumber: Boolean,
 
-      _isDark: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _isDark: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.DocsUrlBehavior,
-      Gerrit.ChangeTableBehavior,
-      Gerrit.FireBehavior,
-    ],
-
-    observers: [
-      '_handlePrefsChanged(_localPrefs.*)',
-      '_handleMenuChanged(_localMenu.splices)',
-      '_handleChangeTableChanged(_localChangeTableColumns, _showNumber)',
-    ],
+    static get observers() {
+      return [
+        '_handlePrefsChanged(_localPrefs.*)',
+        '_handleMenuChanged(_localMenu.splices)',
+        '_handleChangeTableChanged(_localChangeTableColumns, _showNumber)',
+      ];
+    }
 
     attached() {
+      super.attached();
       // Polymer 2: anchor tag won't work on shadow DOM
       // we need to manually calling scrollIntoView when hash changed
       this.listen(window, 'location-change', '_handleLocationChange');
@@ -221,11 +229,12 @@
         // Handle anchor tag for initial load
         this._handleLocationChange();
       });
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'location-change', '_handleLocationChange');
-    },
+    }
 
     _handleLocationChange() {
       // Handle anchor tag after dom attached
@@ -237,25 +246,25 @@
           elem.scrollIntoView();
         }
       }
-    },
+    }
 
     reloadAccountDetail() {
       Promise.all([
         this.$.accountInfo.loadData(),
         this.$.emailEditor.loadData(),
       ]);
-    },
+    }
 
     _isLoading() {
       return this._loading || this._loading === undefined;
-    },
+    }
 
     _copyPrefs(to, from) {
       for (let i = 0; i < PREFS_SECTION_FIELDS.length; i++) {
         this.set([to, PREFS_SECTION_FIELDS[i]],
             this[from][PREFS_SECTION_FIELDS[i]]);
       }
-    },
+    }
 
     _cloneMenu(prefs) {
       const menu = [];
@@ -267,7 +276,7 @@
         });
       }
       this._localMenu = menu;
-    },
+    }
 
     _cloneChangeTableColumns() {
       let columns = this.getVisibleColumns(this.prefs.change_table);
@@ -280,56 +289,56 @@
             this.prefs.change_table);
       }
       this._localChangeTableColumns = columns;
-    },
+    }
 
     _formatChangeTableColumns(changeTableArray) {
       return changeTableArray.map(item => {
         return {column: item};
       });
-    },
+    }
 
     _handleChangeTableChanged() {
       if (this._isLoading()) { return; }
       this._changeTableChanged = true;
-    },
+    }
 
     _handlePrefsChanged(prefs) {
       if (this._isLoading()) { return; }
       this._prefsChanged = true;
-    },
+    }
 
     _handleRelativeDateInChangeTable() {
       this.set('_localPrefs.relative_date_in_change_table',
           this.$.relativeDateInChangeTable.checked);
-    },
+    }
 
     _handleShowSizeBarsInFileListChanged() {
       this.set('_localPrefs.size_bar_in_change_table',
           this.$.showSizeBarsInFileList.checked);
-    },
+    }
 
     _handlePublishCommentsOnPushChanged() {
       this.set('_localPrefs.publish_comments_on_push',
           this.$.publishCommentsOnPush.checked);
-    },
+    }
 
     _handleWorkInProgressByDefault() {
       this.set('_localPrefs.work_in_progress_by_default',
           this.$.workInProgressByDefault.checked);
-    },
+    }
 
     _handleInsertSignedOff() {
       this.set('_localPrefs.signed_off_by', this.$.insertSignedOff.checked);
-    },
+    }
 
     _handleMenuChanged() {
       if (this._isLoading()) { return; }
       this._menuChanged = true;
-    },
+    }
 
     _handleSaveAccountInfo() {
       this.$.accountInfo.save();
-    },
+    }
 
     _handleSavePreferences() {
       this._copyPrefs('prefs', '_localPrefs');
@@ -337,7 +346,7 @@
       return this.$.restAPI.savePreferences(this.prefs).then(() => {
         this._prefsChanged = false;
       });
-    },
+    }
 
     _handleSaveChangeTable() {
       this.set('prefs.change_table', this._localChangeTableColumns);
@@ -346,15 +355,15 @@
       return this.$.restAPI.savePreferences(this.prefs).then(() => {
         this._changeTableChanged = false;
       });
-    },
+    }
 
     _handleSaveDiffPreferences() {
       this.$.diffPrefs.save();
-    },
+    }
 
     _handleSaveEditPreferences() {
       this.$.editPrefs.save();
-    },
+    }
 
     _handleSaveMenu() {
       this.set('prefs.my', this._localMenu);
@@ -362,7 +371,7 @@
       return this.$.restAPI.savePreferences(this.prefs).then(() => {
         this._menuChanged = false;
       });
-    },
+    }
 
     _handleResetMenuButton() {
       return this.$.restAPI.getDefaultPreferences().then(data => {
@@ -370,34 +379,34 @@
           this._cloneMenu(data.my);
         }
       });
-    },
+    }
 
     _handleSaveWatchedProjects() {
       this.$.watchedProjectsEditor.save();
-    },
+    }
 
     _computeHeaderClass(changed) {
       return changed ? 'edited' : '';
-    },
+    }
 
     _handleSaveEmails() {
       this.$.emailEditor.save();
-    },
+    }
 
     _handleNewEmailKeydown(e) {
       if (e.keyCode === 13) { // Enter
         e.stopPropagation();
         this._handleAddEmailButton();
       }
-    },
+    }
 
     _isNewEmailValid(newEmail) {
       return newEmail && newEmail.includes('@');
-    },
+    }
 
     _computeAddEmailButtonEnabled(newEmail, addingEmail) {
       return this._isNewEmailValid(newEmail) && !addingEmail;
-    },
+    }
 
     _handleAddEmailButton() {
       if (!this._isNewEmailValid(this._newEmail)) { return; }
@@ -412,7 +421,7 @@
         this._lastSentVerificationEmail = this._newEmail;
         this._newEmail = '';
       });
-    },
+    }
 
     _getFilterDocsLink(docsBaseUrl) {
       let base = docsBaseUrl;
@@ -424,7 +433,7 @@
       base = base.replace(TRAILING_SLASH_PATTERN, '');
 
       return base + GERRIT_DOCS_FILTER_PATH;
-    },
+    }
 
     _handleToggleDark() {
       if (this._isDark) {
@@ -440,7 +449,7 @@
       this.async(() => {
         window.location.reload();
       }, 1);
-    },
+    }
 
     _showHttpAuth(config) {
       if (config && config.auth &&
@@ -450,6 +459,8 @@
       }
 
       return false;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSettingsView.is, GrSettingsView);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
index 6dcf124..24ee69b 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.html b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.html
index 2a27194..dd02ccd 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.html
@@ -26,7 +26,9 @@
 
 <dom-module id="gr-ssh-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       .statusHeader {
         width: 4em;
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.js b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.js
index 874173a..6e17817 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.js
@@ -17,33 +17,37 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-ssh-editor',
+  class GrSshEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-ssh-editor'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        value: false,
-        notify: true,
-      },
-      _keys: Array,
-      /** @type {?} */
-      _keyToView: Object,
-      _newKey: {
-        type: String,
-        value: '',
-      },
-      _keysToRemove: {
-        type: Array,
-        value() { return []; },
-      },
-    },
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          value: false,
+          notify: true,
+        },
+        _keys: Array,
+        /** @type {?} */
+        _keyToView: Object,
+        _newKey: {
+          type: String,
+          value: '',
+        },
+        _keysToRemove: {
+          type: Array,
+          value() { return []; },
+        },
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getAccountSSHKeys().then(keys => {
         this._keys = keys;
       });
-    },
+    }
 
     save() {
       const promises = this._keysToRemove.map(key => {
@@ -54,22 +58,22 @@
         this._keysToRemove = [];
         this.hasUnsavedChanges = false;
       });
-    },
+    }
 
     _getStatusLabel(isValid) {
       return isValid ? 'Valid' : 'Invalid';
-    },
+    }
 
     _showKey(e) {
       const el = Polymer.dom(e).localTarget;
       const index = parseInt(el.getAttribute('data-index'), 10);
       this._keyToView = this._keys[index];
       this.$.viewKeyOverlay.open();
-    },
+    }
 
     _closeOverlay() {
       this.$.viewKeyOverlay.close();
-    },
+    }
 
     _handleDeleteKey(e) {
       const el = Polymer.dom(e).localTarget;
@@ -77,7 +81,7 @@
       this.push('_keysToRemove', this._keys[index]);
       this.splice('_keys', index, 1);
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleAddKey() {
       this.$.addButton.disabled = true;
@@ -91,10 +95,12 @@
             this.$.addButton.disabled = false;
             this.$.newKey.disabled = false;
           });
-    },
+    }
 
     _computeAddButtonDisabled(newKey) {
       return !newKey.length;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSshEditor.is, GrSshEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html
index d313f5a..912c1fd 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-ssh-editor</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.html b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.html
index 360ea2d..b1ecb2e 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.html
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.html
@@ -24,7 +24,9 @@
 
 <dom-module id="gr-watched-projects-editor">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="gr-form-styles">
       #watchedProjects .notifType {
         text-align: center;
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
index a40094d..f96aa76 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
@@ -25,34 +25,38 @@
     {name: 'Abandons', key: 'notify_abandoned_changes'},
   ];
 
-  Polymer({
-    is: 'gr-watched-projects-editor',
+  class GrWatchedProjectsEditor extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-watched-projects-editor'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        value: false,
-        notify: true,
-      },
-
-      _projects: Array,
-      _projectsToRemove: {
-        type: Array,
-        value() { return []; },
-      },
-      _query: {
-        type: Function,
-        value() {
-          return this._getProjectSuggestions.bind(this);
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          value: false,
+          notify: true,
         },
-      },
-    },
+
+        _projects: Array,
+        _projectsToRemove: {
+          type: Array,
+          value() { return []; },
+        },
+        _query: {
+          type: Function,
+          value() {
+            return this._getProjectSuggestions.bind(this);
+          },
+        },
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getWatchedProjects().then(projs => {
         this._projects = projs;
       });
-    },
+    }
 
     save() {
       let deletePromise;
@@ -72,19 +76,19 @@
             this._projectsToRemove = [];
             this.hasUnsavedChanges = false;
           });
-    },
+    }
 
     _getTypes() {
       return NOTIFICATION_TYPES;
-    },
+    }
 
     _getTypeCount() {
       return this._getTypes().length;
-    },
+    }
 
     _computeCheckboxChecked(project, key) {
       return project.hasOwnProperty(key);
-    },
+    }
 
     _getProjectSuggestions(input) {
       return this.$.restAPI.getSuggestedProjects(input)
@@ -99,7 +103,7 @@
             }
             return projects;
           });
-    },
+    }
 
     _handleRemoveProject(e) {
       const el = Polymer.dom(e).localTarget;
@@ -108,7 +112,7 @@
       this.splice('_projects', index, 1);
       this.push('_projectsToRemove', project);
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _canAddProject(project, text, filter) {
       if ((!project || !project.id) && !text) { return false; }
@@ -126,7 +130,7 @@
       }
 
       return true;
-    },
+    }
 
     _getNewProjectIndex(name, filter) {
       let i;
@@ -138,7 +142,7 @@
         }
       }
       return i;
-    },
+    }
 
     _handleAddProject() {
       const newProject = this.$.newProject.value;
@@ -158,7 +162,7 @@
       this.$.newProject.clear();
       this.$.newFilter.bindValue = '';
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleCheckboxChange(e) {
       const el = Polymer.dom(e).localTarget;
@@ -167,11 +171,13 @@
       const checked = el.checked;
       this.set(['_projects', index, key], !!checked);
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleNotifCellClick(e) {
       const checkbox = Polymer.dom(e.target).querySelector('input');
       if (checkbox) { checkbox.click(); }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrWatchedProjectsEditor.is, GrWatchedProjectsEditor);
 })();
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
index 7a238ec..4bdb00f 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-settings-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
index 10c876d..27b1cc4 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
@@ -14,13 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-account-chip',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrAccountChip extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-chip'; }
     /**
      * Fired to indicate a key was pressed while this chip was focused.
      *
@@ -34,51 +39,52 @@
      * @event remove
      */
 
-    properties: {
-      account: Object,
-      additionalText: String,
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      removable: {
-        type: Boolean,
-        value: false,
-      },
-      showAvatar: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-      transparentBackground: {
-        type: Boolean,
-        value: false,
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        account: Object,
+        additionalText: String,
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        removable: {
+          type: Boolean,
+          value: false,
+        },
+        showAvatar: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+        transparentBackground: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     ready() {
+      super.ready();
       this._getHasAvatars().then(hasAvatars => {
         this.showAvatar = hasAvatars;
       });
-    },
+    }
 
     _getBackgroundClass(transparent) {
       return transparent ? 'transparentBackground' : '';
-    },
+    }
 
     _handleRemoveTap(e) {
       e.preventDefault();
       this.fire('remove', {account: this.account});
-    },
+    }
 
     _getHasAvatars() {
       return this.$.restAPI.getConfig().then(cfg => {
         return Promise.resolve(!!(cfg && cfg.plugin && cfg.plugin.has_avatars));
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountChip.is, GrAccountChip);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.html b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.html
index ae656fd..992ea8407 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.html
@@ -40,7 +40,8 @@
         on-commit="_handleInputCommit"
         clear-on-commit
         warn-uncommitted
-        text="{{_inputText}}">
+        text="{{_inputText}}"
+        vertical-offset="24">
     </gr-autocomplete>
   </template>
   <script src="gr-account-entry.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.js b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.js
index b2e0973..0ed3f19 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.js
@@ -21,9 +21,10 @@
    * gr-account-entry is an element for entering account
    * and/or group with autocomplete support.
    */
-  Polymer({
-    is: 'gr-account-entry',
-
+  class GrAccountEntry extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-account-entry'; }
     /**
      * Fired when an account is entered.
      *
@@ -37,65 +38,70 @@
      *
      * @event account-text-changed
      */
-    properties: {
-      allowAnyInput: Boolean,
-      borderless: Boolean,
-      placeholder: String,
 
-      // suggestFrom = 0 to enable default suggestions.
-      suggestFrom: {
-        type: Number,
-        value: 0,
-      },
+    static get properties() {
+      return {
+        allowAnyInput: Boolean,
+        borderless: Boolean,
+        placeholder: String,
 
-      /** @type {!function(string): !Promise<Array<{name, value}>>} */
-      querySuggestions: {
-        type: Function,
-        notify: true,
-        value() {
-          return input => Promise.resolve([]);
+        // suggestFrom = 0 to enable default suggestions.
+        suggestFrom: {
+          type: Number,
+          value: 0,
         },
-      },
 
-      _config: Object,
-      /** The value of the autocomplete entry. */
-      _inputText: {
-        type: String,
-        observer: '_inputTextChanged',
-      },
+        /** @type {!function(string): !Promise<Array<{name, value}>>} */
+        querySuggestions: {
+          type: Function,
+          notify: true,
+          value() {
+            return input => Promise.resolve([]);
+          },
+        },
 
-    },
+        _config: Object,
+        /** The value of the autocomplete entry. */
+        _inputText: {
+          type: String,
+          observer: '_inputTextChanged',
+        },
+
+      };
+    }
 
     get focusStart() {
       return this.$.input.focusStart;
-    },
+    }
 
     focus() {
       this.$.input.focus();
-    },
+    }
 
     clear() {
       this.$.input.clear();
-    },
+    }
 
     setText(text) {
       this.$.input.setText(text);
-    },
+    }
 
     getText() {
       return this.$.input.text;
-    },
+    }
 
     _handleInputCommit(e) {
       this.fire('add', {value: e.detail.value});
       this.$.input.focus();
-    },
+    }
 
     _inputTextChanged(text) {
       if (text.length && this.allowAnyInput) {
         this.dispatchEvent(new CustomEvent(
             'account-text-changed', {bubbles: true, composed: true}));
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountEntry.is, GrAccountEntry);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html
index 6896af9..0bac7e0 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-entry</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
index 418d2ea..3d96421 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
@@ -17,58 +17,65 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-account-label',
+  /**
+    * @appliesMixin Gerrit.DisplayNameMixin
+    * @appliesMixin Gerrit.TooltipMixin
+    */
+  class GrAccountLabel extends Polymer.mixinBehaviors( [
+    Gerrit.DisplayNameBehavior,
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-label'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * @type {{ name: string, status: string }}
        */
-      account: Object,
-      avatarImageSize: {
-        type: Number,
-        value: 32,
-      },
-      title: {
-        type: String,
-        reflectToAttribute: true,
-        computed: '_computeAccountTitle(account, additionalText)',
-      },
-      additionalText: String,
-      hasTooltip: {
-        type: Boolean,
-        reflectToAttribute: true,
-        computed: '_computeHasTooltip(account)',
-      },
-      hideAvatar: {
-        type: Boolean,
-        value: false,
-      },
-      _serverConfig: {
-        type: Object,
-        value: null,
-      },
-    },
-
-    behaviors: [
-      Gerrit.DisplayNameBehavior,
-      Gerrit.TooltipBehavior,
-    ],
+        account: Object,
+        avatarImageSize: {
+          type: Number,
+          value: 32,
+        },
+        title: {
+          type: String,
+          reflectToAttribute: true,
+          computed: '_computeAccountTitle(account, additionalText)',
+        },
+        additionalText: String,
+        hasTooltip: {
+          type: Boolean,
+          reflectToAttribute: true,
+          computed: '_computeHasTooltip(account)',
+        },
+        hideAvatar: {
+          type: Boolean,
+          value: false,
+        },
+        _serverConfig: {
+          type: Object,
+          value: null,
+        },
+      };
+    }
 
     ready() {
+      super.ready();
       if (!this.additionalText) { this.additionalText = ''; }
       this.$.restAPI.getConfig()
           .then(config => { this._serverConfig = config; });
-    },
+    }
 
     _computeName(account, config) {
       return this.getUserName(config, account, false);
-    },
+    }
 
     _computeStatusTextLength(account, config) {
       // 35 as the max length of the name + status
       return Math.max(10, 35 - this._computeName(account, config).length);
-    },
+    }
 
     _computeAccountTitle(account, tooltip) {
       // Polymer 2: check for undefined
@@ -98,12 +105,12 @@
       }
 
       return result;
-    },
+    }
 
     _computeShowEmailClass(account) {
       if (!account || account.name || !account.email) { return ''; }
       return 'showEmail';
-    },
+    }
 
     _computeEmailStr(account) {
       if (!account || !account.email) {
@@ -113,11 +120,13 @@
         return '(' + account.email + ')';
       }
       return account.email;
-    },
+    }
 
     _computeHasTooltip(account) {
       // If an account has loaded to fire this method, then set to true.
       return !!account;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountLabel.is, GrAccountLabel);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
index f0620d3..f369ae2 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-label</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
index faaf9c3..0764669 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
@@ -17,27 +17,34 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-account-link',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    */
+  class GrAccountLink extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-link'; }
 
-    properties: {
-      additionalText: String,
-      account: Object,
-      avatarImageSize: {
-        type: Number,
-        value: 32,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-    ],
+    static get properties() {
+      return {
+        additionalText: String,
+        account: Object,
+        avatarImageSize: {
+          type: Number,
+          value: 32,
+        },
+      };
+    }
 
     _computeOwnerLink(account) {
       if (!account) { return; }
       return Gerrit.Nav.getUrlForOwner(
           account.email || account.username || account.name ||
           account._account_id);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountLink.is, GrAccountLink);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
index 134c579..e41304f 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-link</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.html b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.html
index 2ce608be..6103d6f 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.html
@@ -66,7 +66,6 @@
         borderless
         hidden$="[[_computeEntryHidden(maxCount, accounts.*, readonly)]]"
         id="entry"
-        change="[[change]]"
         placeholder="[[placeholder]]"
         on-add="_handleAdd"
         on-input-keydown="_handleInputKeydown"
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.js b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.js
index 9897105..48dddb0 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.js
@@ -19,95 +19,101 @@
 
   const VALID_EMAIL_ALERT = 'Please input a valid email.';
 
-  Polymer({
-    is: 'gr-account-list',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrAccountList extends Polymer.mixinBehaviors( [
+    // Used in the tests for gr-account-list and other elements tests.
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-account-list'; }
     /**
      * Fired when user inputs an invalid email address.
      *
      * @event show-alert
      */
 
-    properties: {
-      accounts: {
-        type: Array,
-        value() { return []; },
-        notify: true,
-      },
-      change: Object,
-      filter: Function,
-      placeholder: String,
-      disabled: {
-        type: Function,
-        value: false,
-      },
+    static get properties() {
+      return {
+        accounts: {
+          type: Array,
+          value() { return []; },
+          notify: true,
+        },
+        change: Object,
+        filter: Function,
+        placeholder: String,
+        disabled: {
+          type: Function,
+          value: false,
+        },
 
-      /**
+        /**
        * Returns suggestions and convert them to list item
        * @type {Gerrit.GrSuggestionsProvider}
        */
-      suggestionsProvider: {
-        type: Object,
-      },
+        suggestionsProvider: {
+          type: Object,
+        },
 
-      /**
+        /**
        * Needed for template checking since value is initially set to null.
        * @type {?Object} */
-      pendingConfirmation: {
-        type: Object,
-        value: null,
-        notify: true,
-      },
-      readonly: {
-        type: Boolean,
-        value: false,
-      },
-      /**
+        pendingConfirmation: {
+          type: Object,
+          value: null,
+          notify: true,
+        },
+        readonly: {
+          type: Boolean,
+          value: false,
+        },
+        /**
        * When true, allows for non-suggested inputs to be added.
        */
-      allowAnyInput: {
-        type: Boolean,
-        value: false,
-      },
+        allowAnyInput: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * Array of values (groups/accounts) that are removable. When this prop is
        * undefined, all values are removable.
        */
-      removableValues: Array,
-      maxCount: {
-        type: Number,
-        value: 0,
-      },
+        removableValues: Array,
+        maxCount: {
+          type: Number,
+          value: 0,
+        },
 
-      /** Returns suggestion items
+        /** Returns suggestion items
       * @type {!function(string): Promise<Array<Gerrit.GrSuggestionItem>>}
       */
-      _querySuggestions: {
-        type: Function,
-        value() {
-          return this._getSuggestions.bind(this);
+        _querySuggestions: {
+          type: Function,
+          value() {
+            return this._getSuggestions.bind(this);
+          },
         },
-      },
-    },
+      };
+    }
 
-    behaviors: [
-      // Used in the tests for gr-account-list and other elements tests.
-      Gerrit.FireBehavior,
-    ],
-
-    listeners: {
-      remove: '_handleRemove',
-    },
+    created() {
+      super.created();
+      this.addEventListener('remove',
+          e => this._handleRemove(e));
+    }
 
     get accountChips() {
       return Array.from(
           Polymer.dom(this.root).querySelectorAll('gr-account-chip'));
-    },
+    }
 
     get focusStart() {
       return this.$.entry.focusStart;
-    },
+    }
 
     _getSuggestions(input) {
       const provider = this.suggestionsProvider;
@@ -122,11 +128,11 @@
         return suggestions.map(suggestion =>
           provider.makeSuggestionItem(suggestion));
       });
-    },
+    }
 
     _handleAdd(e) {
       this._addAccountItem(e.detail.value);
-    },
+    }
 
     _addAccountItem(item) {
       // Append new account or group to the accounts property. We add our own
@@ -162,14 +168,14 @@
       }
       this.pendingConfirmation = null;
       return true;
-    },
+    }
 
     confirmGroup(group) {
       group = Object.assign(
           {}, group, {confirmed: true, _pendingAdd: true, _group: true});
       this.push('accounts', group);
       this.pendingConfirmation = null;
-    },
+    }
 
     _computeChipClass(account) {
       const classes = [];
@@ -180,7 +186,7 @@
         classes.push('pendingAdd');
       }
       return classes.join(' ');
-    },
+    }
 
     _accountMatches(a, b) {
       if (a && b) {
@@ -192,7 +198,7 @@
         }
       }
       return a === b;
-    },
+    }
 
     _computeRemovable(account, readonly) {
       if (readonly) { return false; }
@@ -205,13 +211,13 @@
         return !!account._pendingAdd;
       }
       return true;
-    },
+    }
 
     _handleRemove(e) {
       const toRemove = e.detail.account;
       this._removeAccount(toRemove);
       this.$.entry.focus();
-    },
+    }
 
     _removeAccount(toRemove) {
       if (!toRemove || !this._computeRemovable(toRemove, this.readonly)) {
@@ -231,12 +237,12 @@
         }
       }
       console.warn('received remove event for missing account', toRemove);
-    },
+    }
 
     _getNativeInput(paperInput) {
       // In Polymer 2 inputElement isn't nativeInput anymore
       return paperInput.$.nativeInput || paperInput.inputElement;
-    },
+    }
 
     _handleInputKeydown(e) {
       const input = this._getNativeInput(e.detail.input);
@@ -254,7 +260,7 @@
           }
           break;
       }
-    },
+    }
 
     _handleChipKeydown(e) {
       const chip = e.target;
@@ -292,7 +298,7 @@
           }
           break;
       }
-    },
+    }
 
     /**
      * Submit the text of the entry as a reviewer value, if it exists. If it is
@@ -308,7 +314,7 @@
       const wasSubmitted = this._addAccountItem(text);
       if (wasSubmitted) { this.$.entry.clear(); }
       return wasSubmitted;
-    },
+    }
 
     additions() {
       return this.accounts.filter(account => {
@@ -320,10 +326,12 @@
           return {account};
         }
       });
-    },
+    }
 
     _computeEntryHidden(maxCount, accountsRecord, readonly) {
       return (maxCount && maxCount <= accountsRecord.base.length) || readonly;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAccountList.is, GrAccountList);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html
index 202ddf6..9521c5f 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-account-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
index e7c8b2c..433a57b 100644
--- a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
+++ b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
@@ -17,46 +17,51 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-alert',
-
+  class GrAlert extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-alert'; }
     /**
      * Fired when the action button is pressed.
      *
      * @event action
      */
 
-    properties: {
-      text: String,
-      actionText: String,
-      shown: {
-        type: Boolean,
-        value: true,
-        readOnly: true,
-        reflectToAttribute: true,
-      },
-      toast: {
-        type: Boolean,
-        value: true,
-        reflectToAttribute: true,
-      },
+    static get properties() {
+      return {
+        text: String,
+        actionText: String,
+        shown: {
+          type: Boolean,
+          value: true,
+          readOnly: true,
+          reflectToAttribute: true,
+        },
+        toast: {
+          type: Boolean,
+          value: true,
+          reflectToAttribute: true,
+        },
 
-      _hideActionButton: Boolean,
-      _boundTransitionEndHandler: {
-        type: Function,
-        value() { return this._handleTransitionEnd.bind(this); },
-      },
-      _actionCallback: Function,
-    },
+        _hideActionButton: Boolean,
+        _boundTransitionEndHandler: {
+          type: Function,
+          value() { return this._handleTransitionEnd.bind(this); },
+        },
+        _actionCallback: Function,
+      };
+    }
 
     attached() {
+      super.attached();
       this.addEventListener('transitionend', this._boundTransitionEndHandler);
-    },
+    }
 
     detached() {
+      super.detached();
       this.removeEventListener('transitionend',
           this._boundTransitionEndHandler);
-    },
+    }
 
     show(text, opt_actionText, opt_actionCallback) {
       this.text = text;
@@ -65,31 +70,33 @@
       this._actionCallback = opt_actionCallback;
       Gerrit.getRootElement().appendChild(this);
       this._setShown(true);
-    },
+    }
 
     hide() {
       this._setShown(false);
       if (this._hasZeroTransitionDuration()) {
         Gerrit.getRootElement().removeChild(this);
       }
-    },
+    }
 
     _hasZeroTransitionDuration() {
       const style = window.getComputedStyle(this);
       // transitionDuration is always given in seconds.
       const duration = Math.round(parseFloat(style.transitionDuration) * 100);
       return duration === 0;
-    },
+    }
 
     _handleTransitionEnd(e) {
       if (this.shown) { return; }
 
       Gerrit.getRootElement().removeChild(this);
-    },
+    }
 
     _handleActionTap(e) {
       e.preventDefault();
       if (this._actionCallback) { this._actionCallback(); }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAlert.is, GrAlert);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html
index 2338d55..bfcc431 100644
--- a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-alert</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html
index 9208068..cf32e28 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html
@@ -22,6 +22,7 @@
 <link rel="import" href="/bower_components/iron-dropdown/iron-dropdown.html">
 <link rel="import" href="/bower_components/iron-fit-behavior/iron-fit-behavior.html">
 <link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.html">
+<script src="../../../types/polymer-behaviors.js"></script>
 <script src="../../../scripts/rootElement.js"></script>
 <link rel="import" href="../../../styles/shared-styles.html">
 
@@ -59,6 +60,7 @@
       .dropdown-content {
         background: var(--dropdown-background-color);
         box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
+        border-radius: var(--border-radius);
         max-height: 50vh;
         overflow: auto;
       }
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.js b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.js
index b8c76ff..707c426 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.js
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.js
@@ -17,9 +17,19 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-autocomplete-dropdown',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Polymer.IronFitMixin
+    */
+  class GrAutocompleteDropdown extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Polymer.IronFitBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-autocomplete-dropdown'; }
     /**
      * Fired when the dropdown is closed.
      *
@@ -32,57 +42,55 @@
      * @event item-selected
      */
 
-    properties: {
-      index: Number,
-      isHidden: {
-        type: Boolean,
-        value: true,
-        reflectToAttribute: true,
-      },
-      verticalOffset: {
-        type: Number,
-        value: null,
-      },
-      horizontalOffset: {
-        type: Number,
-        value: null,
-      },
-      suggestions: {
-        type: Array,
-        value: () => [],
-        observer: '_resetCursorStops',
-      },
-      _suggestionEls: Array,
-    },
+    static get properties() {
+      return {
+        index: Number,
+        isHidden: {
+          type: Boolean,
+          value: true,
+          reflectToAttribute: true,
+        },
+        verticalOffset: {
+          type: Number,
+          value: null,
+        },
+        horizontalOffset: {
+          type: Number,
+          value: null,
+        },
+        suggestions: {
+          type: Array,
+          value: () => [],
+          observer: '_resetCursorStops',
+        },
+        _suggestionEls: Array,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Polymer.IronFitBehavior,
-    ],
-
-    keyBindings: {
-      up: '_handleUp',
-      down: '_handleDown',
-      enter: '_handleEnter',
-      esc: '_handleEscape',
-      tab: '_handleTab',
-    },
+    get keyBindings() {
+      return {
+        up: '_handleUp',
+        down: '_handleDown',
+        enter: '_handleEnter',
+        esc: '_handleEscape',
+        tab: '_handleTab',
+      };
+    }
 
     close() {
       this.isHidden = true;
-    },
+    }
 
     open() {
       this.isHidden = false;
       this._resetCursorStops();
       // Refit should run after we call Polymer.flush inside _resetCursorStops
       this.refit();
-    },
+    }
 
     getCurrentText() {
       return this.getCursorTarget().dataset.value;
-    },
+    }
 
     _handleUp(e) {
       if (!this.isHidden) {
@@ -90,7 +98,7 @@
         e.stopPropagation();
         this.cursorUp();
       }
-    },
+    }
 
     _handleDown(e) {
       if (!this.isHidden) {
@@ -98,19 +106,19 @@
         e.stopPropagation();
         this.cursorDown();
       }
-    },
+    }
 
     cursorDown() {
       if (!this.isHidden) {
         this.$.cursor.next();
       }
-    },
+    }
 
     cursorUp() {
       if (!this.isHidden) {
         this.$.cursor.previous();
       }
-    },
+    }
 
     _handleTab(e) {
       e.preventDefault();
@@ -119,7 +127,7 @@
         trigger: 'tab',
         selected: this.$.cursor.target,
       });
-    },
+    }
 
     _handleEnter(e) {
       e.preventDefault();
@@ -128,12 +136,12 @@
         trigger: 'enter',
         selected: this.$.cursor.target,
       });
-    },
+    }
 
     _handleEscape() {
       this._fireClose();
       this.close();
-    },
+    }
 
     _handleClickItem(e) {
       e.preventDefault();
@@ -147,15 +155,15 @@
         trigger: 'click',
         selected,
       });
-    },
+    }
 
     _fireClose() {
       this.fire('dropdown-closed');
-    },
+    }
 
     getCursorTarget() {
       return this.$.cursor.target;
-    },
+    }
 
     _resetCursorStops() {
       if (this.suggestions.length > 0) {
@@ -168,14 +176,16 @@
       } else {
         this._suggestionEls = [];
       }
-    },
+    }
 
     _resetCursorIndex() {
       this.$.cursor.setCursorAtIndex(0);
-    },
+    }
 
     _computeLabelClass(item) {
       return item.label ? '' : 'hide';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAutocompleteDropdown.is, GrAutocompleteDropdown);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html
index a7b59d7..5f2ce94 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-autocomplete-dropdown</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
index c9d12ce..e47b661 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
@@ -36,13 +36,14 @@
         margin: 0 var(--spacing-xs);
         vertical-align: top;
       }
-      paper-input:not(.borderless) {
-        border: 1px solid var(--border-color);
+      paper-input.borderless {
+        border: none;
+        padding: 0;
       }
       paper-input {
-        height: var(--line-height-normal);
-        width: 100%;
-        @apply --gr-autocomplete;
+        border: 1px solid var(--border-color);
+        border-radius: var(--border-radius);
+        padding: var(--spacing-s);
         --paper-input-container: {
           padding: 0;
         };
@@ -50,13 +51,25 @@
           font-size: var(--font-size-normal);
           line-height: var(--line-height-normal);
         };
+        /* This is a hack for not being able to set height:0 on the underline
+           of a paper-input 2.2.3 element. All the underline fixes below only
+           actually work in 3.x.x, so the height must be adjusted directly as
+           a workaround until we are on Polymer 3. */
+        height: var(--line-height-normal);
+        --paper-input-container-underline-height: 0;
+        --paper-input-container-underline-wrapper-height: 0;
+        --paper-input-container-underline-focus-height: 0;
+        --paper-input-container-underline-legacy-height: 0;
         --paper-input-container-underline: {
+          height: 0;
           display: none;
         };
         --paper-input-container-underline-focus: {
+          height: 0;
           display: none;
         };
         --paper-input-container-underline-disabled: {
+          height: 0;
           display: none;
         };
       }
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
index da16e2b..3a60255 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
@@ -20,9 +20,17 @@
   const TOKENIZE_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
   const DEBOUNCE_WAIT_MS = 200;
 
-  Polymer({
-    is: 'gr-autocomplete',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrAutocomplete extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-autocomplete'; }
     /**
      * Fired when a value is chosen.
      *
@@ -42,9 +50,10 @@
      * @event input-keydown
      */
 
-    properties: {
+    static get properties() {
+      return {
 
-      /**
+        /**
        * Query for requesting autocomplete suggestions. The function should
        * accept the input as a string parameter and return a promise. The
        * promise yields an array of suggestion objects with "name", "label",
@@ -55,170 +64,174 @@
        *
        * @type {function(string): Promise<?>}
        */
-      query: {
-        type: Function,
-        value() {
-          return function() {
-            return Promise.resolve([]);
-          };
+        query: {
+          type: Function,
+          value() {
+            return function() {
+              return Promise.resolve([]);
+            };
+          },
         },
-      },
 
-      /**
-       * The number of characters that must be typed before suggestions are
-       * made. If threshold is zero, default suggestions are enabled.
-       */
-      threshold: {
-        type: Number,
-        value: 1,
-      },
+        /**
+         * The number of characters that must be typed before suggestions are
+         * made. If threshold is zero, default suggestions are enabled.
+         */
+        threshold: {
+          type: Number,
+          value: 1,
+        },
 
-      allowNonSuggestedValues: Boolean,
-      borderless: Boolean,
-      disabled: Boolean,
-      showSearchIcon: {
-        type: Boolean,
-        value: false,
-      },
-      // Vertical offset needed for a 1em font-size with no vertical padding.
-      // Inputs with additional padding will need to increase vertical offset.
-      verticalOffset: {
-        type: Number,
-        value: 20,
-      },
+        allowNonSuggestedValues: Boolean,
+        borderless: Boolean,
+        disabled: Boolean,
+        showSearchIcon: {
+          type: Boolean,
+          value: false,
+        },
+        /**
+         * Vertical offset needed for an element with 20px line-height, 4px
+         * padding and 1px border (30px height total). Plus 1px spacing between
+         * input and dropdown. Inputs with different line-height or padding will
+         * need to tweak vertical offset.
+         */
+        verticalOffset: {
+          type: Number,
+          value: 31,
+        },
 
-      text: {
-        type: String,
-        value: '',
-        notify: true,
-      },
+        text: {
+          type: String,
+          value: '',
+          notify: true,
+        },
 
-      placeholder: String,
+        placeholder: String,
 
-      clearOnCommit: {
-        type: Boolean,
-        value: false,
-      },
+        clearOnCommit: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
-       * When true, tab key autocompletes but does not fire the commit event.
-       * When false, tab key not caught, and focus is removed from the element.
-       * See Issue 4556, Issue 6645.
-       */
-      tabComplete: {
-        type: Boolean,
-        value: false,
-      },
+        /**
+         * When true, tab key autocompletes but does not fire the commit event.
+         * When false, tab key not caught, and focus is removed from the element.
+         * See Issue 4556, Issue 6645.
+         */
+        tabComplete: {
+          type: Boolean,
+          value: false,
+        },
 
-      value: {
-        type: String,
-        notify: true,
-      },
+        value: {
+          type: String,
+          notify: true,
+        },
 
-      /**
+        /**
        * Multi mode appends autocompleted entries to the value.
        * If false, autocompleted entries replace value.
        */
-      multi: {
-        type: Boolean,
-        value: false,
-      },
+        multi: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * When true and uncommitted text is left in the autocomplete input after
        * blurring, the text will appear red.
        */
-      warnUncommitted: {
-        type: Boolean,
-        value: false,
-      },
+        warnUncommitted: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * When true, querying for suggestions is not debounced w/r/t keypresses
        */
-      noDebounce: {
-        type: Boolean,
-        value: false,
-      },
+        noDebounce: {
+          type: Boolean,
+          value: false,
+        },
 
-      /** @type {?} */
-      _suggestions: {
-        type: Array,
-        value() { return []; },
-      },
+        /** @type {?} */
+        _suggestions: {
+          type: Array,
+          value() { return []; },
+        },
 
-      _suggestionEls: {
-        type: Array,
-        value() { return []; },
-      },
+        _suggestionEls: {
+          type: Array,
+          value() { return []; },
+        },
 
-      _index: Number,
-      _disableSuggestions: {
-        type: Boolean,
-        value: false,
-      },
-      _focused: {
-        type: Boolean,
-        value: false,
-      },
+        _index: Number,
+        _disableSuggestions: {
+          type: Boolean,
+          value: false,
+        },
+        _focused: {
+          type: Boolean,
+          value: false,
+        },
 
-      /** The DOM element of the selected suggestion. */
-      _selected: Object,
-    },
+        /** The DOM element of the selected suggestion. */
+        _selected: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    observers: [
-      '_maybeOpenDropdown(_suggestions, _focused)',
-      '_updateSuggestions(text, threshold, noDebounce)',
-    ],
+    static get observers() {
+      return [
+        '_maybeOpenDropdown(_suggestions, _focused)',
+        '_updateSuggestions(text, threshold, noDebounce)',
+      ];
+    }
 
     get _nativeInput() {
       // In Polymer 2 inputElement isn't nativeInput anymore
       return this.$.input.$.nativeInput || this.$.input.inputElement;
-    },
+    }
 
     attached() {
+      super.attached();
       this.listen(document.body, 'click', '_handleBodyClick');
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(document.body, 'click', '_handleBodyClick');
       this.cancelDebouncer('update-suggestions');
-    },
+    }
 
     get focusStart() {
       return this.$.input;
-    },
+    }
 
     focus() {
       this._nativeInput.focus();
-    },
+    }
 
     selectAll() {
       const nativeInputElement = this._nativeInput;
       if (!this.$.input.value) { return; }
       nativeInputElement.setSelectionRange(0, this.$.input.value.length);
-    },
+    }
 
     clear() {
       this.text = '';
-    },
+    }
 
     _handleItemSelect(e) {
       // Let _handleKeydown deal with keyboard interaction.
       if (e.detail.trigger !== 'click') { return; }
       this._selected = e.detail.selected;
       this._commit();
-    },
+    }
 
     get _inputElement() {
       // Polymer2: this.$ can be undefined when this is first evaluated.
       return this.$ && this.$.input;
-    },
+    }
 
     /**
      * Set the text of the input without triggering the suggestion dropdown.
@@ -228,7 +241,7 @@
       this._disableSuggestions = true;
       this.text = text;
       this._disableSuggestions = false;
-    },
+    }
 
     _onInputFocus() {
       this._focused = true;
@@ -236,14 +249,14 @@
       this.$.input.classList.remove('warnUncommitted');
       // Needed so that --paper-input-container-input updated style is applied.
       this.updateStyles();
-    },
+    }
 
     _onInputBlur() {
       this.$.input.classList.toggle('warnUncommitted',
           this.warnUncommitted && this.text.length && !this._focused);
       // Needed so that --paper-input-container-input updated style is applied.
       this.updateStyles();
-    },
+    }
 
     _updateSuggestions(text, threshold, noDebounce) {
       // Polymer 2: check for undefined
@@ -280,18 +293,18 @@
       } else {
         this.debounce('update-suggestions', update, DEBOUNCE_WAIT_MS);
       }
-    },
+    }
 
     _maybeOpenDropdown(suggestions, focused) {
       if (suggestions.length > 0 && focused) {
         return this.$.suggestions.open();
       }
       return this.$.suggestions.close();
-    },
+    }
 
     _computeClass(borderless) {
       return borderless ? 'borderless' : '';
-    },
+    }
 
     /**
      * _handleKeydown used for key handling in the this.$.input AND all child
@@ -338,7 +351,7 @@
           this._suggestions = [];
       }
       this.fire('input-keydown', {keyCode: e.keyCode, input: this.$.input});
-    },
+    }
 
     _cancel() {
       if (this._suggestions.length) {
@@ -346,7 +359,7 @@
       } else {
         this.fire('cancel');
       }
-    },
+    }
 
     /**
      * @param {boolean=} opt_tabComplete
@@ -358,7 +371,7 @@
 
       this._selected = this.$.suggestions.getCursorTarget();
       this._commit(opt_tabComplete);
-    },
+    }
 
     _updateValue(suggestion, suggestions) {
       if (!suggestion) { return; }
@@ -372,7 +385,7 @@
       } else {
         this.value = completed;
       }
-    },
+    }
 
     _handleBodyClick(e) {
       const eventPath = Polymer.dom(e).path;
@@ -382,13 +395,13 @@
         }
       }
       this._focused = false;
-    },
+    }
 
     _handleSuggestionTap(e) {
       e.stopPropagation();
       this.$.cursor.setCursor(e.target);
       this._commit();
-    },
+    }
 
     /**
      * Commits the suggestion, optionally firing the commit event.
@@ -424,10 +437,12 @@
       }
 
       this._textChangedSinceCommit = false;
-    },
+    }
 
     _computeShowSearchIconClass(showSearchIcon) {
       return showSearchIcon ? 'showSearchIcon' : '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAutocomplete.is, GrAutocomplete);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
index ea1fd50..39329e5 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reviewer-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -335,7 +335,7 @@
     });
 
     test('vertical offset overridden by param if it exists', () => {
-      assert.equal(element.$.suggestions.verticalOffset, 20);
+      assert.equal(element.$.suggestions.verticalOffset, 31);
       element.verticalOffset = 30;
       assert.equal(element.$.suggestions.verticalOffset, 30);
     });
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
index bf56382..e57ba33 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
@@ -17,29 +17,35 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-avatar',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    */
+  class GrAvatar extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-avatar'; }
 
-    properties: {
-      account: {
-        type: Object,
-        observer: '_accountChanged',
-      },
-      imageSize: {
-        type: Number,
-        value: 16,
-      },
-      _hasAvatars: {
-        type: Boolean,
-        value: false,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-    ],
+    static get properties() {
+      return {
+        account: {
+          type: Object,
+          observer: '_accountChanged',
+        },
+        imageSize: {
+          type: Number,
+          value: 16,
+        },
+        _hasAvatars: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       Promise.all([
         this._getConfig(),
         Gerrit.awaitPluginsLoaded(),
@@ -48,15 +54,15 @@
 
         this._updateAvatarURL();
       });
-    },
+    }
 
     _getConfig() {
       return this.$.restAPI.getConfig();
-    },
+    }
 
     _accountChanged(account) {
       this._updateAvatarURL();
-    },
+    }
 
     _updateAvatarURL() {
       if (!this._hasAvatars || !this.account) {
@@ -69,12 +75,12 @@
       if (url) {
         this.style.backgroundImage = 'url("' + url + '")';
       }
-    },
+    }
 
     _getAccounts(account) {
       return account._account_id || account.email || account.username ||
           account.name;
-    },
+    }
 
     _buildAvatarURL(account) {
       if (!account) { return ''; }
@@ -87,6 +93,8 @@
       return this.getBaseUrl() + '/accounts/' +
         encodeURIComponent(this._getAccounts(account)) +
         '/avatar?s=' + this.imageSize;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrAvatar.is, GrAvatar);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
index 9c2aba9..98a75dd 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-avatar</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
index 99d4fe4..1de704a 100644
--- a/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
+++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button.js
@@ -17,65 +17,77 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-button',
+  /**
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.TooltipMixin
+    */
+  class GrButton extends Polymer.mixinBehaviors( [
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-button'; }
 
-    properties: {
-      tooltip: String,
-      downArrow: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-      link: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      loading: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      disabled: {
-        type: Boolean,
-        observer: '_disabledChanged',
-        reflectToAttribute: true,
-      },
-      noUppercase: {
-        type: Boolean,
-        value: false,
-      },
-      _enabledTabindex: {
-        type: String,
-        value: '0',
-      },
-    },
+    static get properties() {
+      return {
+        tooltip: String,
+        downArrow: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+        link: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        loading: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        disabled: {
+          type: Boolean,
+          observer: '_disabledChanged',
+          reflectToAttribute: true,
+        },
+        noUppercase: {
+          type: Boolean,
+          value: false,
+        },
+        _enabledTabindex: {
+          type: String,
+          value: '0',
+        },
+      };
+    }
 
-    listeners: {
-      click: '_handleAction',
-      keydown: '_handleKeydown',
-    },
+    static get observers() {
+      return [
+        '_computeDisabled(disabled, loading)',
+      ];
+    }
 
-    observers: [
-      '_computeDisabled(disabled, loading)',
-    ],
+    created() {
+      super.created();
+      this.addEventListener('click',
+          e => this._handleAction(e));
+      this.addEventListener('keydown',
+          e => this._handleKeydown(e));
+    }
 
-    behaviors: [
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.TooltipBehavior,
-    ],
-
-    hostAttributes: {
-      role: 'button',
-      tabindex: '0',
-    },
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'button');
+      this._ensureAttribute('tabindex', '0');
+    }
 
     _handleAction(e) {
       if (this.disabled) {
         e.preventDefault();
         e.stopImmediatePropagation();
       }
-    },
+    }
 
     _disabledChanged(disabled) {
       if (disabled) {
@@ -83,11 +95,11 @@
       }
       this.setAttribute('tabindex', disabled ? '-1' : this._enabledTabindex);
       this.updateStyles();
-    },
+    }
 
     _computeDisabled(disabled, loading) {
       return disabled || loading;
-    },
+    }
 
     _handleKeydown(e) {
       if (this.modifierPressed(e)) { return; }
@@ -98,6 +110,8 @@
         e.stopPropagation();
         this.click();
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrButton.is, GrButton);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html b/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html
index 2593ed1..d8a5443 100644
--- a/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-button/gr-button_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-button</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
index a83bc2b..05e759f 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
@@ -17,31 +17,34 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-change-star',
-
+  class GrChangeStar extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-change-star'; }
     /**
      * Fired when star state is toggled.
      *
      * @event toggle-star
      */
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?} */
-      change: {
-        type: Object,
-        notify: true,
-      },
-    },
+        change: {
+          type: Object,
+          notify: true,
+        },
+      };
+    }
 
     _computeStarClass(starred) {
       return starred ? 'active' : '';
-    },
+    }
 
     _computeStarIcon(starred) {
       // Hollow star is used to indicate inactive state.
       return `gr-icons:star${starred ? '' : '-border'}`;
-    },
+    }
 
     toggleStar() {
       const newVal = !this.change.starred;
@@ -51,6 +54,8 @@
         composed: true,
         detail: {change: this.change, starred: newVal},
       }));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeStar.is, GrChangeStar);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
index 7ee22a7..60c504a 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-star</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.js b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.js
index 3afbe54..35b8ef8 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.js
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status.js
@@ -29,38 +29,46 @@
       'It will not appear on dashboards unless you are CC\'ed or assigned, ' +
       'and email notifications will be silenced until the review is started.';
 
+  const MERGE_CONFLICT_TOOLTIP = 'This change has merge conflicts. ' +
+      'Download the patch and run "git rebase master". ' +
+      'Upload a new patchset after resolving all merge conflicts.';
+
   const PRIVATE_TOOLTIP = 'This change is only visible to its owner and ' +
       'current reviewers (or anyone with "View Private Changes" permission).';
 
-  Polymer({
-    is: 'gr-change-status',
+  class GrChangeStatus extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-change-status'; }
 
-    properties: {
-      flat: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      status: {
-        type: String,
-        observer: '_updateChipDetails',
-      },
-      tooltipText: {
-        type: String,
-        value: '',
-      },
-    },
+    static get properties() {
+      return {
+        flat: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        status: {
+          type: String,
+          observer: '_updateChipDetails',
+        },
+        tooltipText: {
+          type: String,
+          value: '',
+        },
+      };
+    }
 
     _computeStatusString(status) {
       if (status === ChangeStates.WIP && !this.flat) {
         return 'Work in Progress';
       }
       return status;
-    },
+    }
 
     _toClassName(str) {
       return str.toLowerCase().replace(/\s/g, '-');
-    },
+    }
 
     _updateChipDetails(status, previousStatus) {
       if (previousStatus) {
@@ -75,10 +83,15 @@
         case ChangeStates.PRIVATE:
           this.tooltipText = PRIVATE_TOOLTIP;
           break;
+        case ChangeStates.MERGE_CONFLICT:
+          this.tooltipText = MERGE_CONFLICT_TOOLTIP;
+          break;
         default:
           this.tooltipText = '';
           break;
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeStatus.is, GrChangeStatus);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html
index 3ac4016..96a1840 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-status/gr-change-status_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-status</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -35,6 +35,17 @@
 </test-fixture>
 
 <script>
+  const WIP_TOOLTIP = 'This change isn\'t ready to be reviewed or submitted. ' +
+      'It will not appear on dashboards unless you are CC\'ed or assigned, ' +
+      'and email notifications will be silenced until the review is started.';
+
+  const MERGE_CONFLICT_TOOLTIP = 'This change has merge conflicts. ' +
+    'Download the patch and run "git rebase master". ' +
+    'Upload a new patchset after resolving all merge conflicts.';
+
+  const PRIVATE_TOOLTIP = 'This change is only visible to its owner and ' +
+      'current reviewers (or anyone with "View Private Changes" permission).';
+
   suite('gr-change-status tests', () => {
     let element;
     let sandbox;
@@ -51,7 +62,7 @@
     test('WIP', () => {
       element.status = 'WIP';
       assert.equal(element.$$('.chip').innerText, 'Work in Progress');
-      assert.isDefined(element.tooltipText);
+      assert.equal(element.tooltipText, WIP_TOOLTIP);
       assert.isTrue(element.classList.contains('wip'));
     });
 
@@ -81,14 +92,14 @@
     test('merge conflict', () => {
       element.status = 'Merge Conflict';
       assert.equal(element.$$('.chip').innerText, element.status);
-      assert.equal(element.tooltipText, '');
+      assert.equal(element.tooltipText, MERGE_CONFLICT_TOOLTIP);
       assert.isTrue(element.classList.contains('merge-conflict'));
     });
 
     test('private', () => {
       element.status = 'Private';
       assert.equal(element.$$('.chip').innerText, element.status);
-      assert.isDefined(element.tooltipText);
+      assert.equal(element.tooltipText, PRIVATE_TOOLTIP);
       assert.isTrue(element.classList.contains('private'));
     });
 
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
index bbd7ddf..d7510ec 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
@@ -87,14 +87,13 @@
           as="comment">
         <gr-comment
             comment="{{comment}}"
-            robot-button-disabled="[[_hideActions(_showActions, _lastComment)]]"
+            robot-button-disabled="[[_shouldDisableAction(_showActions, _lastComment)]]"
             change-num="[[changeNum]]"
             patch-num="[[patchNum]]"
             draft="[[_isDraft(comment)]]"
             show-actions="[[_showActions]]"
             comment-side="[[comment.__commentSide]]"
             side="[[comment.side]]"
-            root-id="[[rootId]]"
             project-config="[[_projectConfig]]"
             on-create-fix-comment="_handleCommentFix"
             on-comment-discard="_handleCommentDiscard"
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
index ff5576cb..72fc45d 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
@@ -20,9 +20,22 @@
   const UNRESOLVED_EXPAND_COUNT = 5;
   const NEWLINE_PATTERN = /\n/g;
 
-  Polymer({
-    is: 'gr-comment-thread',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.PathListMixin
+    */
+  class GrCommentThread extends Polymer.mixinBehaviors( [
+    /**
+       * Not used in this element rather other elements tests
+       */
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.PathListBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-comment-thread'; }
     /**
      * Fired when the thread should be discarded.
      *
@@ -36,122 +49,122 @@
      */
 
     /**
-      * gr-comment-thread exposes the following attributes that allow a
-      * diff widget like gr-diff to show the thread in the right location:
-      *
-      * line-num:
-      *     1-based line number or undefined if it refers to the entire file.
-      *
-      * comment-side:
-      *     "left" or "right". These indicate which of the two diffed versions
-      *     the comment relates to. In the case of unified diff, the left
-      *     version is the one whose line number column is further to the left.
-      *
-      * range:
-      *     The range of text that the comment refers to (start_line,
-      *     start_character, end_line, end_character), serialized as JSON. If
-      *     set, range's end_line will have the same value as line-num. Line
-      *     numbers are 1-based, char numbers are 0-based. The start position
-      *     (start_line, start_character) is inclusive, and the end position
-      *     (end_line, end_character) is exclusive.
-      */
-    properties: {
-      changeNum: String,
-      comments: {
-        type: Array,
-        value() { return []; },
-      },
-      /**
+              * gr-comment-thread exposes the following attributes that allow a
+              * diff widget like gr-diff to show the thread in the right location:
+              *
+              * line-num:
+              *     1-based line number or undefined if it refers to the entire file.
+              *
+              * comment-side:
+              *     "left" or "right". These indicate which of the two diffed versions
+              *     the comment relates to. In the case of unified diff, the left
+              *     version is the one whose line number column is further to the left.
+              *
+              * range:
+              *     The range of text that the comment refers to (start_line,
+              *     start_character, end_line, end_character), serialized as JSON. If
+              *     set, range's end_line will have the same value as line-num. Line
+              *     numbers are 1-based, char numbers are 0-based. The start position
+              *     (start_line, start_character) is inclusive, and the end position
+              *     (end_line, end_character) is exclusive.
+              */
+    static get properties() {
+      return {
+        changeNum: String,
+        comments: {
+          type: Array,
+          value() { return []; },
+        },
+        /**
        * @type {?{start_line: number, start_character: number, end_line: number,
        *          end_character: number}}
        */
-      range: {
-        type: Object,
-        reflectToAttribute: true,
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      commentSide: {
-        type: String,
-        reflectToAttribute: true,
-      },
-      patchNum: String,
-      path: String,
-      projectName: {
-        type: String,
-        observer: '_projectNameChanged',
-      },
-      hasDraft: {
-        type: Boolean,
-        notify: true,
-        reflectToAttribute: true,
-      },
-      isOnParent: {
-        type: Boolean,
-        value: false,
-      },
-      parentIndex: {
-        type: Number,
-        value: null,
-      },
-      rootId: {
-        type: String,
-        notify: true,
-        computed: '_computeRootId(comments.*)',
-      },
-      /**
+        range: {
+          type: Object,
+          reflectToAttribute: true,
+        },
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        commentSide: {
+          type: String,
+          reflectToAttribute: true,
+        },
+        patchNum: String,
+        path: String,
+        projectName: {
+          type: String,
+          observer: '_projectNameChanged',
+        },
+        hasDraft: {
+          type: Boolean,
+          notify: true,
+          reflectToAttribute: true,
+        },
+        isOnParent: {
+          type: Boolean,
+          value: false,
+        },
+        parentIndex: {
+          type: Number,
+          value: null,
+        },
+        rootId: {
+          type: String,
+          notify: true,
+          computed: '_computeRootId(comments.*)',
+        },
+        /**
        * If this is true, the comment thread also needs to have the change and
        * line properties property set
        */
-      showFilePath: {
-        type: Boolean,
-        value: false,
-      },
-      /** Necessary only if showFilePath is true or when used with gr-diff */
-      lineNum: {
-        type: Number,
-        reflectToAttribute: true,
-      },
-      unresolved: {
-        type: Boolean,
-        notify: true,
-        reflectToAttribute: true,
-      },
-      _showActions: Boolean,
-      _lastComment: Object,
-      _orderedComments: Array,
-      _projectConfig: Object,
-    },
+        showFilePath: {
+          type: Boolean,
+          value: false,
+        },
+        /** Necessary only if showFilePath is true or when used with gr-diff */
+        lineNum: {
+          type: Number,
+          reflectToAttribute: true,
+        },
+        unresolved: {
+          type: Boolean,
+          notify: true,
+          reflectToAttribute: true,
+        },
+        _showActions: Boolean,
+        _lastComment: Object,
+        _orderedComments: Array,
+        _projectConfig: Object,
+      };
+    }
 
-    behaviors: [
-      /**
-       * Not used in this element rather other elements tests
-       */
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.PathListBehavior,
-    ],
+    static get observers() {
+      return [
+        '_commentsChanged(comments.*)',
+      ];
+    }
 
-    listeners: {
-      'comment-update': '_handleCommentUpdate',
-    },
+    get keyBindings() {
+      return {
+        'e shift+e': '_handleEKey',
+      };
+    }
 
-    observers: [
-      '_commentsChanged(comments.*)',
-    ],
-
-    keyBindings: {
-      'e shift+e': '_handleEKey',
-    },
+    created() {
+      super.created();
+      this.addEventListener('comment-update',
+          e => this._handleCommentUpdate(e));
+    }
 
     attached() {
+      super.attached();
       this._getLoggedIn().then(loggedIn => {
         this._showActions = loggedIn;
       });
       this._setInitialExpandedState();
-    },
+    }
 
     addOrEditDraft(opt_lineNum, opt_range) {
       const lastComment = this.comments[this.comments.length - 1] || {};
@@ -169,39 +182,39 @@
         const unresolved = lastComment ? lastComment.unresolved : undefined;
         this.addDraft(opt_lineNum, range, unresolved);
       }
-    },
+    }
 
     addDraft(opt_lineNum, opt_range, opt_unresolved) {
       const draft = this._newDraft(opt_lineNum, opt_range);
       draft.__editing = true;
       draft.unresolved = opt_unresolved === false ? opt_unresolved : true;
       this.push('comments', draft);
-    },
+    }
 
     fireRemoveSelf() {
       this.dispatchEvent(new CustomEvent('thread-discard',
           {detail: {rootId: this.rootId}, bubbles: false}));
-    },
+    }
 
     _getDiffUrlForComment(projectName, changeNum, path, patchNum) {
       return Gerrit.Nav.getUrlForDiffById(changeNum,
           projectName, path, patchNum,
           null, this.lineNum);
-    },
+    }
 
     _computeDisplayPath(path) {
       const lineString = this.lineNum ? `#${this.lineNum}` : '';
       return this.computeDisplayPath(path) + lineString;
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _commentsChanged() {
       this._orderedComments = this._sortedComments(this.comments);
       this.updateThreadProperties();
-    },
+    }
 
     updateThreadProperties() {
       if (this._orderedComments.length) {
@@ -209,16 +222,20 @@
         this.unresolved = this._lastComment.unresolved;
         this.hasDraft = this._lastComment.__draft;
       }
-    },
+    }
+
+    _shouldDisableAction(_showActions, _lastComment) {
+      return !_showActions || !_lastComment || !!_lastComment.__draft;
+    }
 
     _hideActions(_showActions, _lastComment) {
-      return !_showActions || !_lastComment || !!_lastComment.__draft ||
+      return this._shouldDisableAction(_showActions, _lastComment) ||
         !!_lastComment.robot_id;
-    },
+    }
 
     _getLastComment() {
       return this._orderedComments[this._orderedComments.length - 1] || {};
-    },
+    }
 
     _handleEKey(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
@@ -231,7 +248,7 @@
         if (this.modifierPressed(e)) { return; }
         this._expandCollapseComments(false);
       }
-    },
+    }
 
     _expandCollapseComments(actionIsCollapse) {
       const comments =
@@ -239,7 +256,7 @@
       for (const comment of comments) {
         comment.collapsed = actionIsCollapse;
       }
-    },
+    }
 
     /**
      * Sets the initial state of the comment thread.
@@ -259,7 +276,7 @@
           comment.collapsed = !isRobotComment && resolvedThread;
         }
       }
-    },
+    }
 
     _sortedComments(comments) {
       return comments.slice().sort((c1, c2) => {
@@ -275,7 +292,7 @@
         // If same date, fall back to sorting by id.
         return dateCompare ? dateCompare : c1.id.localeCompare(c2.id);
       });
-    },
+    }
 
     _createReplyComment(parent, content, opt_isEditing,
         opt_unresolved) {
@@ -309,11 +326,11 @@
           commentEl.save();
         }, 1);
       }
-    },
+    }
 
     _isDraft(comment) {
       return !!comment.__draft;
-    },
+    }
 
     /**
      * @param {boolean=} opt_quote
@@ -326,25 +343,25 @@
         quoteStr = '> ' + msg.replace(NEWLINE_PATTERN, '\n> ') + '\n\n';
       }
       this._createReplyComment(comment, quoteStr, true, comment.unresolved);
-    },
+    }
 
     _handleCommentReply(e) {
       this._processCommentReply();
-    },
+    }
 
     _handleCommentQuote(e) {
       this._processCommentReply(true);
-    },
+    }
 
     _handleCommentAck(e) {
       const comment = this._lastComment;
       this._createReplyComment(comment, 'Ack', false, false);
-    },
+    }
 
     _handleCommentDone(e) {
       const comment = this._lastComment;
       this._createReplyComment(comment, 'Done', false, false);
-    },
+    }
 
     _handleCommentFix(e) {
       const comment = e.detail.comment;
@@ -352,7 +369,7 @@
       const quoteStr = '> ' + msg.replace(NEWLINE_PATTERN, '\n> ') + '\n\n';
       const response = quoteStr + 'Please Fix';
       this._createReplyComment(comment, response, false, true);
-    },
+    }
 
     _commentElWithDraftID(id) {
       const els = Polymer.dom(this.root).querySelectorAll('gr-comment');
@@ -362,7 +379,7 @@
         }
       }
       return null;
-    },
+    }
 
     _newReply(inReplyTo, opt_lineNum, opt_message, opt_unresolved,
         opt_range) {
@@ -376,7 +393,7 @@
         d.unresolved = opt_unresolved;
       }
       return d;
-    },
+    }
 
     /**
      * @param {number=} opt_lineNum
@@ -402,12 +419,12 @@
         d.parent = this.parentIndex;
       }
       return d;
-    },
+    }
 
     _getSide(isOnParent) {
       if (isOnParent) { return 'PARENT'; }
       return 'REVISION';
-    },
+    }
 
     _computeRootId(comments) {
       // Keep the root ID even if the comment was removed, so that notification
@@ -415,7 +432,7 @@
       if (!comments.base.length) { return this.rootId; }
       const rootComment = comments.base[0];
       return rootComment.id || rootComment.__draftID;
-    },
+    }
 
     _handleCommentDiscard(e) {
       const diffCommentEl = Polymer.dom(e).rootTarget;
@@ -445,13 +462,13 @@
               changeComment.message);
         }
       }
-    },
+    }
 
     _handleCommentSavedOrDiscarded(e) {
       this.dispatchEvent(new CustomEvent('thread-changed',
           {detail: {rootId: this.rootId, path: this.path},
             bubbles: false}));
-    },
+    }
 
     _handleCommentUpdate(e) {
       const comment = e.detail.comment;
@@ -467,7 +484,7 @@
       // observers, the this.set() call above will not cause a thread update in
       // some situations.
       this.updateThreadProperties();
-    },
+    }
 
     _indexOf(comment, arr) {
       for (let i = 0; i < arr.length; i++) {
@@ -478,11 +495,11 @@
         }
       }
       return -1;
-    },
+    }
 
     _computeHostClass(unresolved) {
       return unresolved ? 'unresolved' : '';
-    },
+    }
 
     /**
      * Load the project config when a project name has been provided.
@@ -493,6 +510,8 @@
       this.$.restAPI.getProjectConfig(name).then(config => {
         this._projectConfig = config;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCommentThread.is, GrCommentThread);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
index d3946e6..17e0b1f 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-comment-thread</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -152,6 +152,24 @@
       assert.isTrue(addDraftStub.called);
     });
 
+    test('_shouldDisableAction', () => {
+      let showActions = true;
+      const lastComment = {};
+      assert.equal(
+          element._shouldDisableAction(showActions, lastComment), false);
+      showActions = false;
+      assert.equal(
+          element._shouldDisableAction(showActions, lastComment), true);
+      showActions = true;
+      lastComment.__draft = true;
+      assert.equal(
+          element._shouldDisableAction(showActions, lastComment), true);
+      const robotComment = {};
+      robotComment.robot_id = true;
+      assert.equal(
+          element._shouldDisableAction(showActions, robotComment), false);
+    });
+
     test('_hideActions', () => {
       let showActions = true;
       const lastComment = {};
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
index 8ad261c..46fa3cf 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.html
@@ -305,7 +305,6 @@
         <gr-formatted-text class="message"
             content="[[comment.message]]"
             no-trailing-margin="[[!comment.__draft]]"
-            collapsed="[[collapsed]]"
             config="[[projectConfig.commentlinks]]"></gr-formatted-text>
         <div hidden$="[[!comment.robot_run_id]]" class="message">
           <div class="runIdInformation" hidden$="[[collapsed]]">
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
index 6881929..dd2855c 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.js
@@ -31,9 +31,17 @@
 
   const FILE = 'FILE';
 
-  Polymer({
-    is: 'gr-comment',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrComment extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-comment'; }
     /**
      * Fired when the create fix comment action is triggered.
      *
@@ -64,108 +72,111 @@
      * @event comment-anchor-tap
      */
 
-    properties: {
-      changeNum: String,
-      /** @type {?} */
-      comment: {
-        type: Object,
-        notify: true,
-        observer: '_commentChanged',
-      },
-      isRobotComment: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      draft: {
-        type: Boolean,
-        value: false,
-        observer: '_draftChanged',
-      },
-      editing: {
-        type: Boolean,
-        value: false,
-        observer: '_editingChanged',
-      },
-      discarding: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      hasChildren: Boolean,
-      patchNum: String,
-      showActions: Boolean,
-      _showHumanActions: Boolean,
-      _showRobotActions: Boolean,
-      collapsed: {
-        type: Boolean,
-        value: true,
-        observer: '_toggleCollapseClass',
-      },
-      /** @type {?} */
-      projectConfig: Object,
-      robotButtonDisabled: Boolean,
-      _isAdmin: {
-        type: Boolean,
-        value: false,
-      },
+    static get properties() {
+      return {
+        changeNum: String,
+        /** @type {?} */
+        comment: {
+          type: Object,
+          notify: true,
+          observer: '_commentChanged',
+        },
+        isRobotComment: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        draft: {
+          type: Boolean,
+          value: false,
+          observer: '_draftChanged',
+        },
+        editing: {
+          type: Boolean,
+          value: false,
+          observer: '_editingChanged',
+        },
+        discarding: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        hasChildren: Boolean,
+        patchNum: String,
+        showActions: Boolean,
+        _showHumanActions: Boolean,
+        _showRobotActions: Boolean,
+        collapsed: {
+          type: Boolean,
+          value: true,
+          observer: '_toggleCollapseClass',
+        },
+        /** @type {?} */
+        projectConfig: Object,
+        robotButtonDisabled: Boolean,
+        _isAdmin: {
+          type: Boolean,
+          value: false,
+        },
 
-      _xhrPromise: Object, // Used for testing.
-      _messageText: {
-        type: String,
-        value: '',
-        observer: '_messageTextChanged',
-      },
-      commentSide: String,
+        _xhrPromise: Object, // Used for testing.
+        _messageText: {
+          type: String,
+          value: '',
+          observer: '_messageTextChanged',
+        },
+        commentSide: String,
+        side: String,
 
-      resolved: Boolean,
+        resolved: Boolean,
 
-      _numPendingDraftRequests: {
-        type: Object,
-        value:
+        _numPendingDraftRequests: {
+          type: Object,
+          value:
             {number: 0}, // Intentional to share the object across instances.
-      },
+        },
 
-      _enableOverlay: {
-        type: Boolean,
-        value: false,
-      },
+        _enableOverlay: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * Property for storing references to overlay elements. When the overlays
        * are moved to Gerrit.getRootElement() to be shown they are no-longer
        * children, so they can't be queried along the tree, so they are stored
        * here.
        */
-      _overlays: {
-        type: Object,
-        value: () => ({}),
-      },
-    },
+        _overlays: {
+          type: Object,
+          value: () => ({}),
+        },
+      };
+    }
 
-    observers: [
-      '_commentMessageChanged(comment.message)',
-      '_loadLocalDraft(changeNum, patchNum, comment)',
-      '_isRobotComment(comment)',
-      '_calculateActionstoShow(showActions, isRobotComment)',
-    ],
+    static get observers() {
+      return [
+        '_commentMessageChanged(comment.message)',
+        '_loadLocalDraft(changeNum, patchNum, comment)',
+        '_isRobotComment(comment)',
+        '_calculateActionstoShow(showActions, isRobotComment)',
+      ];
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    keyBindings: {
-      'ctrl+enter meta+enter ctrl+s meta+s': '_handleSaveKey',
-      'esc': '_handleEsc',
-    },
+    get keyBindings() {
+      return {
+        'ctrl+enter meta+enter ctrl+s meta+s': '_handleSaveKey',
+        'esc': '_handleEsc',
+      };
+    }
 
     attached() {
+      super.attached();
       if (this.editing) {
         this.collapsed = false;
       } else if (this.comment) {
@@ -174,18 +185,19 @@
       this._getIsAdmin().then(isAdmin => {
         this._isAdmin = isAdmin;
       });
-    },
+    }
 
     detached() {
+      super.detached();
       this.cancelDebouncer('fire-update');
       if (this.textarea) {
         this.textarea.closeDropdown();
       }
-    },
+    }
 
     get textarea() {
       return this.$$('#editTextarea');
-    },
+    }
 
     get confirmDeleteOverlay() {
       if (!this._overlays.confirmDelete) {
@@ -194,7 +206,7 @@
         this._overlays.confirmDelete = this.$$('#confirmDeleteOverlay');
       }
       return this._overlays.confirmDelete;
-    },
+    }
 
     get confirmDiscardOverlay() {
       if (!this._overlays.confirmDiscard) {
@@ -203,11 +215,11 @@
         this._overlays.confirmDiscard = this.$$('#confirmDiscardOverlay');
       }
       return this._overlays.confirmDiscard;
-    },
+    }
 
     _computeShowHideIcon(collapsed) {
       return collapsed ? 'gr-icons:expand-more' : 'gr-icons:expand-less';
-    },
+    }
 
     _calculateActionstoShow(showActions, isRobotComment) {
       // Polymer 2: check for undefined
@@ -217,19 +229,19 @@
 
       this._showHumanActions = showActions && !isRobotComment;
       this._showRobotActions = showActions && isRobotComment;
-    },
+    }
 
     _isRobotComment(comment) {
       this.isRobotComment = !!comment.robot_id;
-    },
+    }
 
     isOnParent() {
       return this.side === 'PARENT';
-    },
+    }
 
     _getIsAdmin() {
       return this.$.restAPI.getIsAdmin();
-    },
+    }
 
     /**
      * @param {*=} opt_comment
@@ -272,7 +284,7 @@
       });
 
       return this._xhrPromise;
-    },
+    }
 
     _eraseDraftComment() {
       // Prevents a race condition in which removing the draft comment occurs
@@ -286,7 +298,7 @@
         line: this.comment.line,
         range: this.comment.range,
       });
-    },
+    }
 
     _commentChanged(comment) {
       this.editing = !!comment.__editing;
@@ -294,7 +306,7 @@
       if (this.editing) { // It's a new draft/reply, notify.
         this._fireUpdate();
       }
-    },
+    }
 
     /**
      * @param {!Object=} opt_mixin
@@ -306,21 +318,21 @@
         comment: this.comment,
         patchNum: this.patchNum,
       });
-    },
+    }
 
     _fireSave() {
       this.fire('comment-save', this._getEventPayload());
-    },
+    }
 
     _fireUpdate() {
       this.debounce('fire-update', () => {
         this.fire('comment-update', this._getEventPayload());
       });
-    },
+    }
 
     _draftChanged(draft) {
       this.$.container.classList.toggle('draft', draft);
-    },
+    }
 
     _editingChanged(editing, previousValue) {
       // Polymer 2: observer fires when at least one property is defined.
@@ -345,11 +357,11 @@
           this.textarea.putCursorAtEnd();
         }, 1);
       }
-    },
+    }
 
     _computeDeleteButtonClass(isAdmin, draft) {
       return isAdmin && !draft ? 'showDeleteButtons' : '';
-    },
+    }
 
     _computeSaveDisabled(draft, comment, resolved) {
       // If resolved state has changed and a msg exists, save should be enabled.
@@ -357,7 +369,7 @@
         return false;
       }
       return !draft || draft.trim() === '';
-    },
+    }
 
     _handleSaveKey(e) {
       if (!this._computeSaveDisabled(this._messageText, this.comment,
@@ -365,18 +377,18 @@
         e.preventDefault();
         this._handleSave(e);
       }
-    },
+    }
 
     _handleEsc(e) {
       if (!this._messageText.length) {
         e.preventDefault();
         this._handleCancel(e);
       }
-    },
+    }
 
     _handleToggleCollapsed() {
       this.collapsed = !this.collapsed;
-    },
+    }
 
     _toggleCollapseClass(collapsed) {
       if (collapsed) {
@@ -384,11 +396,11 @@
       } else {
         this.$.container.classList.remove('collapsed');
       }
-    },
+    }
 
     _commentMessageChanged(message) {
       this._messageText = message || '';
-    },
+    }
 
     _messageTextChanged(newValue, oldValue) {
       if (!this.comment || (this.comment && this.comment.id)) {
@@ -413,7 +425,7 @@
           this.$.storage.setDraftComment(commentLocation, message);
         }
       }, STORAGE_DEBOUNCE_INTERVAL);
-    },
+    }
 
     _handleAnchorClick(e) {
       e.preventDefault();
@@ -428,14 +440,14 @@
           side: this.side,
         },
       }));
-    },
+    }
 
     _handleEdit(e) {
       e.preventDefault();
       this._messageText = this.comment.message;
       this.editing = true;
       this.$.reporting.recordDraftInteraction();
-    },
+    }
 
     _handleSave(e) {
       e.preventDefault();
@@ -449,7 +461,7 @@
       const timer = this.$.reporting.getTimer(timingLabel);
       this.set('comment.__editing', false);
       return this.save().then(() => { timer.end(); });
-    },
+    }
 
     _handleCancel(e) {
       e.preventDefault();
@@ -462,12 +474,12 @@
       }
       this._messageText = this.comment.message;
       this.editing = false;
-    },
+    }
 
     _fireDiscard() {
       this.cancelDebouncer('fire-update');
       this.fire('comment-discard', this._getEventPayload());
-    },
+    }
 
     _handleFix() {
       this.dispatchEvent(new CustomEvent('create-fix-comment', {
@@ -475,7 +487,7 @@
         composed: true,
         detail: this._getEventPayload(),
       }));
-    },
+    }
 
     _handleDiscard(e) {
       e.preventDefault();
@@ -490,14 +502,14 @@
         this.confirmDiscardOverlay.querySelector('#confirmDiscardDialog')
             .resetFocus();
       });
-    },
+    }
 
     _handleConfirmDiscard(e) {
       e.preventDefault();
       const timer = this.$.reporting.getTimer(REPORT_DISCARD_DRAFT);
       this._closeConfirmDiscardOverlay();
       return this._discardDraft().then(() => { timer.end(); });
-    },
+    }
 
     _discardDraft() {
       if (!this.comment.__draft) {
@@ -528,11 +540,11 @@
       });
 
       return this._xhrPromise;
-    },
+    }
 
     _closeConfirmDiscardOverlay() {
       this._closeOverlay(this.confirmDiscardOverlay);
-    },
+    }
 
     _getSavingMessage(numPending) {
       if (numPending === 0) {
@@ -543,17 +555,17 @@
         numPending,
         numPending === 1 ? DRAFT_SINGULAR : DRAFT_PLURAL,
       ].join(' ');
-    },
+    }
 
     _showStartRequest() {
       const numPending = ++this._numPendingDraftRequests.number;
       this._updateRequestToast(numPending);
-    },
+    }
 
     _showEndRequest() {
       const numPending = --this._numPendingDraftRequests.number;
       this._updateRequestToast(numPending);
-    },
+    }
 
     _handleFailedDraftRequest() {
       this._numPendingDraftRequests.number--;
@@ -561,7 +573,7 @@
       // Cancel the debouncer so that error toasts from the error-manager will
       // not be overridden.
       this.cancelDebouncer('draft-toast');
-    },
+    }
 
     _updateRequestToast(numPending) {
       const message = this._getSavingMessage(numPending);
@@ -572,7 +584,7 @@
         document.body.dispatchEvent(new CustomEvent(
             'show-alert', {detail: {message}, bubbles: true, composed: true}));
       }, TOAST_DEBOUNCE_INTERVAL);
-    },
+    }
 
     _saveDraft(draft) {
       this._showStartRequest();
@@ -585,7 +597,7 @@
             }
             return result;
           });
-    },
+    }
 
     _deleteDraft(draft) {
       this._showStartRequest();
@@ -598,11 +610,11 @@
         }
         return result;
       });
-    },
+    }
 
     _getPatchNum() {
       return this.isOnParent() ? 'PARENT' : this.patchNum;
-    },
+    }
 
     _loadLocalDraft(changeNum, patchNum, comment) {
       // Polymer 2: check for undefined
@@ -631,7 +643,7 @@
       if (draft) {
         this.set('comment.message', draft.message);
       }
-    },
+    }
 
     _handleToggleResolved() {
       this.$.reporting.recordDraftInteraction();
@@ -645,25 +657,25 @@
         // Save the resolved state immediately.
         this.save(payload.comment);
       }
-    },
+    }
 
     _handleCommentDelete() {
       this._openOverlay(this.confirmDeleteOverlay);
-    },
+    }
 
     _handleCancelDeleteComment() {
       this._closeOverlay(this.confirmDeleteOverlay);
-    },
+    }
 
     _openOverlay(overlay) {
       Polymer.dom(Gerrit.getRootElement()).appendChild(overlay);
       return overlay.open();
-    },
+    }
 
     _closeOverlay(overlay) {
       Polymer.dom(Gerrit.getRootElement()).removeChild(overlay);
       overlay.close();
-    },
+    }
 
     _handleConfirmDeleteComment() {
       const dialog =
@@ -674,6 +686,8 @@
             this._handleCancelDeleteComment();
             this.comment = newComment;
           });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrComment.is, GrComment);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
index 560f9fa..de75b40 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-comment</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js
index c2075f0..79cd251 100644
--- a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js
+++ b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.js
@@ -17,9 +17,15 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-confirm-delete-comment-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrConfirmDeleteCommentDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-confirm-delete-comment-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -32,28 +38,29 @@
      * @event cancel
      */
 
-    properties: {
-      message: String,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        message: String,
+      };
+    }
 
     resetFocus() {
       this.$.messageInput.textarea.focus();
-    },
+    }
 
     _handleConfirmTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', {reason: this.message}, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrConfirmDeleteCommentDialog.is,
+      GrConfirmDeleteCommentDialog);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
index 0d8d163..f58db39 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
@@ -47,6 +47,12 @@
         height: 1.2em;
         width: 1.2em;
       }
+      gr-button {
+        --gr-button: {
+          padding: 1px 4px;
+        }
+      }
+
     </style>
     <div class="text">
       <iron-input
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.js b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.js
index 3e87202..6c062f6 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.js
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.js
@@ -19,34 +19,38 @@
 
   const COPY_TIMEOUT_MS = 1000;
 
-  Polymer({
-    is: 'gr-copy-clipboard',
+  class GrCopyClipboard extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-copy-clipboard'; }
 
-    properties: {
-      text: String,
-      buttonTitle: String,
-      hasTooltip: {
-        type: Boolean,
-        value: false,
-      },
-      hideInput: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        text: String,
+        buttonTitle: String,
+        hasTooltip: {
+          type: Boolean,
+          value: false,
+        },
+        hideInput: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     focusOnCopy() {
       this.$.button.focus();
-    },
+    }
 
     _computeInputClass(hideInput) {
       return hideInput ? 'hideInput' : '';
-    },
+    }
 
     _handleInputClick(e) {
       e.preventDefault();
       Polymer.dom(e).rootTarget.select();
-    },
+    }
 
     _copyToClipboard() {
       if (this.hideInput) {
@@ -62,6 +66,8 @@
       this.async(
           () => this.$.icon.icon = 'gr-icons:content-copy',
           COPY_TIMEOUT_MS);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCopyClipboard.is, GrCopyClipboard);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html
index 9cec20e..14490f0 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-copy-clipboard</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html b/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html
index d061ac2..5022766 100644
--- a/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-count-string-formatter/gr-count-string-formatter_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-count-string-formatter</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
index 4e9ff76..4232ef9 100644
--- a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
+++ b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager.js
@@ -22,72 +22,77 @@
     KEEP_VISIBLE: 'keep-visible',
   };
 
-  Polymer({
-    is: 'gr-cursor-manager',
+  class GrCursorManager extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-cursor-manager'; }
 
-    properties: {
-      stops: {
-        type: Array,
-        value() {
-          return [];
+    static get properties() {
+      return {
+        stops: {
+          type: Array,
+          value() {
+            return [];
+          },
+          observer: '_updateIndex',
         },
-        observer: '_updateIndex',
-      },
-      /**
+        /**
        * @type (?Object)
        */
-      target: {
-        type: Object,
-        notify: true,
-        observer: '_scrollToTarget',
-      },
-      /**
+        target: {
+          type: Object,
+          notify: true,
+          observer: '_scrollToTarget',
+        },
+        /**
        * The height of content intended to be included with the target.
        * @type (?number)
        */
-      _targetHeight: Number,
+        _targetHeight: Number,
 
-      /**
+        /**
        * The index of the current target (if any). -1 otherwise.
        */
-      index: {
-        type: Number,
-        value: -1,
-        notify: true,
-      },
+        index: {
+          type: Number,
+          value: -1,
+          notify: true,
+        },
 
-      /**
+        /**
        * The class to apply to the current target. Use null for no class.
        */
-      cursorTargetClass: {
-        type: String,
-        value: null,
-      },
+        cursorTargetClass: {
+          type: String,
+          value: null,
+        },
 
-      /**
+        /**
        * The scroll behavior for the cursor. Values are 'never' and
        * 'keep-visible'. 'keep-visible' will only scroll if the cursor is beyond
        * the viewport.
        * TODO (beckysiegel) figure out why it can be undefined
        * @type (string|undefined)
        */
-      scrollBehavior: {
-        type: String,
-        value: ScrollBehavior.NEVER,
-      },
+        scrollBehavior: {
+          type: String,
+          value: ScrollBehavior.NEVER,
+        },
 
-      /**
+        /**
        * When true, will call element.focus() during scrolling.
        */
-      focusOnMove: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        focusOnMove: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     detached() {
+      super.detached();
       this.unsetCursor();
-    },
+    }
 
     /**
      * Move the cursor forward. Clipped to the ends of the stop list.
@@ -104,11 +109,11 @@
 
     next(opt_condition, opt_getTargetHeight, opt_clipToTop) {
       this._moveCursor(1, opt_condition, opt_getTargetHeight, opt_clipToTop);
-    },
+    }
 
     previous(opt_condition) {
       this._moveCursor(-1, opt_condition);
-    },
+    }
 
     /**
      * Set the cursor to an arbitrary element.
@@ -129,32 +134,32 @@
       this._decorateTarget();
 
       if (opt_noScroll) { this.scrollBehavior = behavior; }
-    },
+    }
 
     unsetCursor() {
       this._unDecorateTarget();
       this.index = -1;
       this.target = null;
       this._targetHeight = null;
-    },
+    }
 
     isAtStart() {
       return this.index === 0;
-    },
+    }
 
     isAtEnd() {
       return this.index === this.stops.length - 1;
-    },
+    }
 
     moveToStart() {
       if (this.stops.length) {
         this.setCursor(this.stops[0]);
       }
-    },
+    }
 
     setCursorAtIndex(index, opt_noScroll) {
       this.setCursor(this.stops[index], opt_noScroll);
-    },
+    }
 
     /**
      * Move the cursor forward or backward by delta. Clipped to the beginning or
@@ -199,19 +204,19 @@
       if (this.focusOnMove) { this.target.focus(); }
 
       this._decorateTarget();
-    },
+    }
 
     _decorateTarget() {
       if (this.target && this.cursorTargetClass) {
         this.target.classList.add(this.cursorTargetClass);
       }
-    },
+    }
 
     _unDecorateTarget() {
       if (this.target && this.cursorTargetClass) {
         this.target.classList.remove(this.cursorTargetClass);
       }
-    },
+    }
 
     /**
      * Get the next stop index indicated by the delta direction.
@@ -247,7 +252,7 @@
       }
 
       return newIndex;
-    },
+    }
 
     _updateIndex() {
       if (!this.target) {
@@ -261,7 +266,7 @@
       } else {
         this.index = newIndex;
       }
-    },
+    }
 
     /**
      * Calculate where the element is relative to the window.
@@ -276,7 +281,7 @@
         top += offsetParent.offsetTop;
       }
       return top;
-    },
+    }
 
     /**
      * @return {boolean}
@@ -286,12 +291,12 @@
       return this.scrollBehavior === ScrollBehavior.KEEP_VISIBLE &&
           top > dims.pageYOffset &&
           top < dims.pageYOffset + dims.innerHeight;
-    },
+    }
 
     _calculateScrollToValue(top, target) {
       const dims = this._getWindowDims();
       return top - (dims.innerHeight / 3) + (target.offsetHeight / 2);
-    },
+    }
 
     _scrollToTarget() {
       if (!this.target || this.scrollBehavior === ScrollBehavior.NEVER) {
@@ -319,7 +324,7 @@
       // element appears to be below the center of the window even when it
       // isn't.
       window.scrollTo(dims.scrollX, scrollToValue);
-    },
+    }
 
     _getWindowDims() {
       return {
@@ -328,6 +333,8 @@
         innerHeight: window.innerHeight,
         pageYOffset: window.pageYOffset,
       };
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCursorManager.is, GrCursorManager);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.html b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.html
index b51e44c..103b41a 100644
--- a/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-cursor-manager/gr-cursor-manager_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-cursor-manager</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
index 5b1ef7f..f79c1b6 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter.js
@@ -31,50 +31,56 @@
     MONTH_DAY_YEAR: 'MMM DD, YYYY', // Aug 29, 1997
   };
 
-  Polymer({
-    is: 'gr-date-formatter',
+  /**
+    * @appliesMixin Gerrit.TooltipMixin
+    */
+  class GrDateFormatter extends Polymer.mixinBehaviors( [
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-date-formatter'; }
 
-    properties: {
-      dateStr: {
-        type: String,
-        value: null,
-        notify: true,
-      },
-      showDateAndTime: {
-        type: Boolean,
-        value: false,
-      },
+    static get properties() {
+      return {
+        dateStr: {
+          type: String,
+          value: null,
+          notify: true,
+        },
+        showDateAndTime: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * When true, the detailed date appears in a GR-TOOLTIP rather than in the
        * native browser tooltip.
        */
-      hasTooltip: Boolean,
+        hasTooltip: Boolean,
 
-      /**
+        /**
        * The title to be used as the native tooltip or by the tooltip behavior.
        */
-      title: {
-        type: String,
-        reflectToAttribute: true,
-        computed: '_computeFullDateStr(dateStr, _timeFormat)',
-      },
+        title: {
+          type: String,
+          reflectToAttribute: true,
+          computed: '_computeFullDateStr(dateStr, _timeFormat)',
+        },
 
-      _timeFormat: String, // No default value to prevent flickering.
-      _relative: Boolean, // No default value to prevent flickering.
-    },
-
-    behaviors: [
-      Gerrit.TooltipBehavior,
-    ],
+        _timeFormat: String, // No default value to prevent flickering.
+        _relative: Boolean, // No default value to prevent flickering.
+      };
+    }
 
     attached() {
+      super.attached();
       this._loadPreferences();
-    },
+    }
 
     _getUtcOffsetString() {
       return ' UTC' + moment().format('Z');
-    },
+    }
 
     _loadPreferences() {
       return this._getLoggedIn().then(loggedIn => {
@@ -88,7 +94,7 @@
           this._loadRelative(),
         ]);
       });
-    },
+    }
 
     _loadTimeFormat() {
       return this._getPreferences().then(preferences => {
@@ -104,22 +110,22 @@
             throw Error('Invalid time format: ' + timeFormat);
         }
       });
-    },
+    }
 
     _loadRelative() {
       return this._getPreferences().then(prefs => {
         // prefs.relative_date_in_change_table is not set when false.
         this._relative = !!(prefs && prefs.relative_date_in_change_table);
       });
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     /**
      * Return true if date is within 24 hours and on the same day.
@@ -127,7 +133,7 @@
     _isWithinDay(now, date) {
       const diff = -date.diff(now);
       return diff < Duration.DAY && date.day() === now.getDay();
-    },
+    }
 
     /**
      * Returns true if date is from one to six months.
@@ -136,7 +142,7 @@
       const diff = -date.diff(now);
       return (date.day() !== now.getDay() || diff >= Duration.DAY) &&
           diff < 180 * Duration.DAY;
-    },
+    }
 
     _computeDateStr(dateStr, timeFormat, relative, showDateAndTime) {
       if (!dateStr) { return ''; }
@@ -163,13 +169,13 @@
         }
       }
       return date.format(format);
-    },
+    }
 
     _timeToSecondsFormat(timeFormat) {
       return timeFormat === TimeFormats.TIME_12 ?
         TimeFormats.TIME_12_WITH_SEC :
         TimeFormats.TIME_24_WITH_SEC;
-    },
+    }
 
     _computeFullDateStr(dateStr, timeFormat) {
       // Polymer 2: check for undefined
@@ -186,6 +192,8 @@
       let format = TimeFormats.MONTH_DAY_YEAR + ', ';
       format += this._timeToSecondsFormat(timeFormat);
       return date.format(format) + this._getUtcOffsetString();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDateFormatter.is, GrDateFormatter);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
index 99af4e6..fffd38e 100644
--- a/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-date-formatter/gr-date-formatter_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-date-formatter</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.js b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.js
index 68dc537..b84434e 100644
--- a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.js
+++ b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.js
@@ -17,9 +17,15 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-dialog',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrDialog extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-dialog'; }
     /**
      * Fired when the confirm button is pressed.
      *
@@ -32,33 +38,32 @@
      * @event cancel
      */
 
-    properties: {
-      confirmLabel: {
-        type: String,
-        value: 'Confirm',
-      },
-      // Supplying an empty cancel label will hide the button completely.
-      cancelLabel: {
-        type: String,
-        value: 'Cancel',
-      },
-      disabled: {
-        type: Boolean,
-        value: false,
-      },
-      confirmOnEnter: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        confirmLabel: {
+          type: String,
+          value: 'Confirm',
+        },
+        // Supplying an empty cancel label will hide the button completely.
+        cancelLabel: {
+          type: String,
+          value: 'Cancel',
+        },
+        disabled: {
+          type: Boolean,
+          value: false,
+        },
+        confirmOnEnter: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    hostAttributes: {
-      role: 'dialog',
-    },
+    ready() {
+      super.ready();
+      this._ensureAttribute('role', 'dialog');
+    }
 
     _handleConfirm(e) {
       if (this.disabled) { return; }
@@ -66,24 +71,26 @@
       e.preventDefault();
       e.stopPropagation();
       this.fire('confirm', null, {bubbles: false});
-    },
+    }
 
     _handleCancelTap(e) {
       e.preventDefault();
       e.stopPropagation();
       this.fire('cancel', null, {bubbles: false});
-    },
+    }
 
     _handleKeydown(e) {
       if (this.confirmOnEnter && e.keyCode === 13) { this._handleConfirm(e); }
-    },
+    }
 
     resetFocus() {
       this.$.confirm.focus();
-    },
+    }
 
     _computeCancelClass(cancelLabel) {
       return cancelLabel.length ? '' : 'hidden';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDialog.is, GrDialog);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html
index 1456e77..ced925e 100644
--- a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-dialog</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.html b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.html
index 9d85d44..367e30c 100644
--- a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.html
+++ b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.html
@@ -24,8 +24,12 @@
 
 <dom-module id="gr-diff-preferences">
   <template>
-    <style include="shared-styles"></style>
-    <style include="gr-form-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
+    <style include="gr-form-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <div id="diffPreferences" class="gr-form-styles">
       <section>
         <span class="title">Context</span>
diff --git a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.js b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.js
index 36fdf5b..6e34bbc 100644
--- a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.js
+++ b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences.js
@@ -17,62 +17,68 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-diff-preferences',
+  class GrDiffPreferences extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-diff-preferences'; }
 
-    properties: {
-      hasUnsavedChanges: {
-        type: Boolean,
-        notify: true,
-        value: false,
-      },
+    static get properties() {
+      return {
+        hasUnsavedChanges: {
+          type: Boolean,
+          notify: true,
+          value: false,
+        },
 
-      /** @type {?} */
-      diffPrefs: Object,
-    },
+        /** @type {?} */
+        diffPrefs: Object,
+      };
+    }
 
     loadData() {
       return this.$.restAPI.getDiffPreferences().then(prefs => {
         this.diffPrefs = prefs;
       });
-    },
+    }
 
     _handleDiffPrefsChanged() {
       this.hasUnsavedChanges = true;
-    },
+    }
 
     _handleLineWrappingTap() {
       this.set('diffPrefs.line_wrapping', this.$.lineWrappingInput.checked);
       this._handleDiffPrefsChanged();
-    },
+    }
 
     _handleShowTabsTap() {
       this.set('diffPrefs.show_tabs', this.$.showTabsInput.checked);
       this._handleDiffPrefsChanged();
-    },
+    }
 
     _handleShowTrailingWhitespaceTap() {
       this.set('diffPrefs.show_whitespace_errors',
           this.$.showTrailingWhitespaceInput.checked);
       this._handleDiffPrefsChanged();
-    },
+    }
 
     _handleSyntaxHighlightTap() {
       this.set('diffPrefs.syntax_highlighting',
           this.$.syntaxHighlightInput.checked);
       this._handleDiffPrefsChanged();
-    },
+    }
 
     _handleAutomaticReviewTap() {
       this.set('diffPrefs.manual_review',
           !this.$.automaticReviewInput.checked);
       this._handleDiffPrefsChanged();
-    },
+    }
 
     save() {
       return this.$.restAPI.saveDiffPreferences(this.diffPrefs).then(res => {
         this.hasUnsavedChanges = false;
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDiffPreferences.is, GrDiffPreferences);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html
index 4d2a1a4..fa1ade5 100644
--- a/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-diff-preferences/gr-diff-preferences_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-diff-preferences</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.js b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.js
index 121aa35..8ee4820 100644
--- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.js
+++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands.js
@@ -17,40 +17,46 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-download-commands',
+  /**
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrDownloadCommands extends Polymer.mixinBehaviors( [
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-download-commands'; }
 
-    properties: {
-      commands: Array,
-      _loggedIn: {
-        type: Boolean,
-        value: false,
-        observer: '_loggedInChanged',
-      },
-      schemes: Array,
-      selectedScheme: {
-        type: String,
-        notify: true,
-      },
-    },
-
-    behaviors: [
-      Gerrit.RESTClientBehavior,
-    ],
+    static get properties() {
+      return {
+        commands: Array,
+        _loggedIn: {
+          type: Boolean,
+          value: false,
+          observer: '_loggedInChanged',
+        },
+        schemes: Array,
+        selectedScheme: {
+          type: String,
+          notify: true,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       this._getLoggedIn().then(loggedIn => {
         this._loggedIn = loggedIn;
       });
-    },
+    }
 
     focusOnCopy() {
       this.$$('gr-shell-command').focusOnCopy();
-    },
+    }
 
     _getLoggedIn() {
       return this.$.restAPI.getLoggedIn();
-    },
+    }
 
     _loggedInChanged(loggedIn) {
       if (!loggedIn) { return; }
@@ -60,7 +66,7 @@
           this.selectedScheme = prefs.download_scheme.toLowerCase();
         }
       });
-    },
+    }
 
     _handleTabChange(e) {
       const scheme = this.schemes[e.detail.value];
@@ -71,15 +77,17 @@
               {download_scheme: this.selectedScheme});
         }
       }
-    },
+    }
 
     _computeSelected(schemes, selectedScheme) {
       return (schemes.findIndex(scheme => scheme === selectedScheme) || 0)
           + '';
-    },
+    }
 
     _computeShowTabs(schemes) {
       return schemes.length > 1 ? '' : 'hidden';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDownloadCommands.is, GrDownloadCommands);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html
index 85a5b1f..7d4b341 100644
--- a/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-download-commands/gr-download-commands_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-download-commands</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html
index e397ae6..f5f25d2 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.html
@@ -142,7 +142,7 @@
       <paper-listbox
           class="dropdown-content"
           slot="dropdown-content"
-          attr-for-selected="value"
+          attr-for-selected="data-value"
           selected="{{value}}"
           on-tap="_handleDropdownTap">
         <template is="dom-repeat"
@@ -150,7 +150,7 @@
             initial-count="[[initialCount]]">
           <paper-item
               disabled="[[item.disabled]]"
-              value="[[item.value]]">
+              data-value$="[[item.value]]">
             <div class="topContent">
               <div>[[item.text]]</div>
               <template is="dom-if" if="[[item.date]]">
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js
index 1f0d01c..2197733 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.js
@@ -45,9 +45,10 @@
    */
   Defs.item;
 
-  Polymer({
-    is: 'gr-dropdown-list',
-
+  class GrDropdownList extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-dropdown-list'; }
     /**
      * Fired when the selected value changes
      *
@@ -56,24 +57,28 @@
      * @property {string|number} value
      */
 
-    properties: {
-      initialCount: Number,
-      /** @type {!Array<!Defs.item>} */
-      items: Object,
-      text: String,
-      disabled: {
-        type: Boolean,
-        value: false,
-      },
-      value: {
-        type: String,
-        notify: true,
-      },
-    },
+    static get properties() {
+      return {
+        initialCount: Number,
+        /** @type {!Array<!Defs.item>} */
+        items: Object,
+        text: String,
+        disabled: {
+          type: Boolean,
+          value: false,
+        },
+        value: {
+          type: String,
+          notify: true,
+        },
+      };
+    }
 
-    observers: [
-      '_handleValueChange(value, items)',
-    ],
+    static get observers() {
+      return [
+        '_handleValueChange(value, items)',
+      ];
+    }
 
     /**
      * Handle a click on the iron-dropdown element.
@@ -85,7 +90,7 @@
       this.async(() => {
         this.$.dropdown.close();
       }, 1);
-    },
+    }
 
     /**
      * Handle a click on the button to open the dropdown.
@@ -93,18 +98,18 @@
      */
     _showDropdownTapHandler(e) {
       this._open();
-    },
+    }
 
     /**
      * Open the dropdown.
      */
     _open() {
       this.$.dropdown.open();
-    },
+    }
 
     _computeMobileText(item) {
       return item.mobileText ? item.mobileText : item.text;
-    },
+    }
 
     _handleValueChange(value, items) {
       // Polymer 2: check for undefined
@@ -123,6 +128,8 @@
         detail: {value},
         bubbles: false,
       }));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDropdownList.is, GrDropdownList);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
index 10378b1..8d098df 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-dropdown-list</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -109,7 +109,7 @@
 
         assert.isNotOk(Polymer.dom(items[0]).querySelector('gr-date-formatter'));
         assert.isNotOk(Polymer.dom(items[0]).querySelector('.bottomContent'));
-        assert.equal(items[0].value, element.items[0].value);
+        assert.equal(items[0].dataset.value, element.items[0].value);
         assert.equal(mobileItems[0].value, element.items[0].value);
         assert.equal(Polymer.dom(items[0]).querySelector('.topContent div')
             .innerText, element.items[0].text);
@@ -126,7 +126,7 @@
 
         assert.isNotOk(Polymer.dom(items[1]).querySelector('gr-date-formatter'));
         assert.isOk(Polymer.dom(items[1]).querySelector('.bottomContent'));
-        assert.equal(items[1].value, element.items[1].value);
+        assert.equal(items[1].dataset.value, element.items[1].value);
         assert.equal(mobileItems[1].value, element.items[1].value);
         assert.equal(Polymer.dom(items[1]).querySelector('.topContent div')
             .innerText, element.items[1].text);
@@ -147,7 +147,7 @@
 
         assert.isOk(Polymer.dom(items[2]).querySelector('gr-date-formatter'));
         assert.isOk(Polymer.dom(items[2]).querySelector('.bottomContent'));
-        assert.equal(items[2].value, element.items[2].value);
+        assert.equal(items[2].dataset.value, element.items[2].value);
         assert.equal(mobileItems[2].value, element.items[2].value);
         assert.equal(Polymer.dom(items[2]).querySelector('.topContent div')
             .innerText, element.items[2].text);
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
index 7273268..9725f0c 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
@@ -20,9 +20,17 @@
   const REL_NOOPENER = 'noopener';
   const REL_EXTERNAL = 'external';
 
-  Polymer({
-    is: 'gr-dropdown',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrDropdown extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-dropdown'; }
     /**
      * Fired when a non-link dropdown item with the given ID is tapped.
      *
@@ -35,60 +43,59 @@
      * @event tap-item
      */
 
-    properties: {
-      items: {
-        type: Array,
-        observer: '_resetCursorStops',
-      },
-      downArrow: Boolean,
-      topContent: Object,
-      horizontalAlign: {
-        type: String,
-        value: 'left',
-      },
+    static get properties() {
+      return {
+        items: {
+          type: Array,
+          observer: '_resetCursorStops',
+        },
+        downArrow: Boolean,
+        topContent: Object,
+        horizontalAlign: {
+          type: String,
+          value: 'left',
+        },
 
-      /**
+        /**
        * Style the dropdown trigger as a link (rather than a button).
        */
-      link: {
-        type: Boolean,
-        value: false,
-      },
+        link: {
+          type: Boolean,
+          value: false,
+        },
 
-      verticalOffset: {
-        type: Number,
-        value: 40,
-      },
+        verticalOffset: {
+          type: Number,
+          value: 40,
+        },
 
-      /**
+        /**
        * List the IDs of dropdown buttons to be disabled. (Note this only
        * diisables bittons and not link entries.)
        */
-      disabledIds: {
-        type: Array,
-        value() { return []; },
-      },
+        disabledIds: {
+          type: Array,
+          value() { return []; },
+        },
 
-      /**
+        /**
        * The elements of the list.
        */
-      _listElements: {
-        type: Array,
-        value() { return []; },
-      },
-    },
+        _listElements: {
+          type: Array,
+          value() { return []; },
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    keyBindings: {
-      'down': '_handleDown',
-      'enter space': '_handleEnter',
-      'tab': '_handleTab',
-      'up': '_handleUp',
-    },
+    get keyBindings() {
+      return {
+        'down': '_handleDown',
+        'enter space': '_handleEnter',
+        'tab': '_handleTab',
+        'up': '_handleUp',
+      };
+    }
 
     /**
      * Handle the up key.
@@ -102,7 +109,7 @@
       } else {
         this._open();
       }
-    },
+    }
 
     /**
      * Handle the down key.
@@ -116,7 +123,7 @@
       } else {
         this._open();
       }
-    },
+    }
 
     /**
      * Handle the tab key.
@@ -128,7 +135,7 @@
         e.preventDefault();
         e.stopPropagation();
       }
-    },
+    }
 
     /**
      * Handle the enter key.
@@ -146,7 +153,7 @@
       } else {
         this._open();
       }
-    },
+    }
 
     /**
      * Handle a click on the iron-dropdown element.
@@ -154,7 +161,7 @@
      */
     _handleDropdownTap(e) {
       this._close();
-    },
+    }
 
     /**
      * Hanlde a click on the button to open the dropdown.
@@ -168,7 +175,7 @@
       } else {
         this._open();
       }
-    },
+    }
 
     /**
      * Open the dropdown and initialize the cursor.
@@ -178,7 +185,7 @@
       this._resetCursorStops();
       this.$.cursor.setCursorAtIndex(0);
       this.$.cursor.target.focus();
-    },
+    }
 
     _close() {
       // async is needed so that that the click event is fired before the
@@ -186,7 +193,7 @@
       this.async(() => {
         this.$.dropdown.close();
       }, 1);
-    },
+    }
 
     /**
      * Get the class for a top-content item based on the given boolean.
@@ -195,7 +202,7 @@
      */
     _getClassIfBold(bold) {
       return bold ? 'bold-text' : '';
-    },
+    }
 
     /**
      * Build a URL for the given host and path. The base URL will be only added,
@@ -208,7 +215,7 @@
       const base = path.startsWith(this.getBaseUrl()) ?
         '' : this.getBaseUrl();
       return '//' + host + base + path;
-    },
+    }
 
     /**
      * Build a scheme-relative URL for the current host. Will include the base
@@ -220,7 +227,7 @@
     _computeRelativeURL(path) {
       const host = window.location.host;
       return this._computeURLHelper(host, path);
-    },
+    }
 
     /**
      * Compute the URL for a link object.
@@ -235,7 +242,7 @@
         return link.url;
       }
       return this._computeRelativeURL(link.url);
-    },
+    }
 
     /**
      * Compute the value for the rel attribute of an anchor for the given link
@@ -249,7 +256,7 @@
       if (link.target) { return REL_NOOPENER; }
       if (link.external) { return REL_EXTERNAL; }
       return null;
-    },
+    }
 
     /**
      * Handle a click on an item of the dropdown.
@@ -264,7 +271,7 @@
         }
         this.dispatchEvent(new CustomEvent('tap-item-' + id));
       }
-    },
+    }
 
     /**
      * If a dropdown item is shown as a button, get the class for the button.
@@ -275,7 +282,7 @@
      */
     _computeDisabledClass(id, disabledIdsRecord) {
       return disabledIdsRecord.base.includes(id) ? 'disabled' : '';
-    },
+    }
 
     /**
      * Recompute the stops for the dropdown item cursor.
@@ -286,14 +293,16 @@
         this._listElements = Array.from(
             Polymer.dom(this.root).querySelectorAll('li'));
       }
-    },
+    }
 
     _computeHasTooltip(tooltip) {
       return !!tooltip;
-    },
+    }
 
     _computeIsDownload(link) {
       return !!link.download;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDropdown.is, GrDropdown);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
index 295f746..4b5ccb4 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-dropdown</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.html b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.html
index 7f85082..45ddfc8 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.html
@@ -20,6 +20,7 @@
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../gr-storage/gr-storage.html">
+<link rel="import" href="../gr-button/gr-button.html">
 
 <dom-module id="gr-editable-content">
   <template>
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.js b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.js
index 75c0201..49b1025 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.js
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.js
@@ -20,9 +20,15 @@
   const RESTORED_MESSAGE = 'Content restored from a previous edit.';
   const STORAGE_DEBOUNCE_INTERVAL_MS = 400;
 
-  Polymer({
-    is: 'gr-editable-content',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrEditableContent extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-editable-content'; }
     /**
      * Fired when the save button is pressed.
      *
@@ -41,42 +47,40 @@
      * @event show-alert
      */
 
-    properties: {
-      content: {
-        notify: true,
-        type: String,
-      },
-      disabled: {
-        reflectToAttribute: true,
-        type: Boolean,
-        value: false,
-      },
-      editing: {
-        observer: '_editingChanged',
-        type: Boolean,
-        value: false,
-      },
-      removeZeroWidthSpace: Boolean,
-      // If no storage key is provided, content is not stored.
-      storageKey: String,
-      _saveDisabled: {
-        computed: '_computeSaveDisabled(disabled, content, _newContent)',
-        type: Boolean,
-        value: true,
-      },
-      _newContent: {
-        type: String,
-        observer: '_newContentChanged',
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+    static get properties() {
+      return {
+        content: {
+          notify: true,
+          type: String,
+        },
+        disabled: {
+          reflectToAttribute: true,
+          type: Boolean,
+          value: false,
+        },
+        editing: {
+          observer: '_editingChanged',
+          type: Boolean,
+          value: false,
+        },
+        removeZeroWidthSpace: Boolean,
+        // If no storage key is provided, content is not stored.
+        storageKey: String,
+        _saveDisabled: {
+          computed: '_computeSaveDisabled(disabled, content, _newContent)',
+          type: Boolean,
+          value: true,
+        },
+        _newContent: {
+          type: String,
+          observer: '_newContentChanged',
+        },
+      };
+    }
 
     focusTextarea() {
       this.$$('iron-autogrow-textarea').textarea.focus();
-    },
+    }
 
     _newContentChanged(newContent, oldContent) {
       if (!this.storageKey) { return; }
@@ -88,7 +92,7 @@
           this.$.storage.eraseEditableContentItem(this.storageKey);
         }
       }, STORAGE_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _editingChanged(editing) {
       if (!editing) { return; }
@@ -114,7 +118,7 @@
       this._newContent = this.removeZeroWidthSpace ?
         content.replace(/^R=\u200B/gm, 'R=') :
         content;
-    },
+    }
 
     _computeSaveDisabled(disabled, content, newContent) {
       // Polymer 2: check for undefined
@@ -127,17 +131,19 @@
       }
 
       return disabled || (content === newContent);
-    },
+    }
 
     _handleSave(e) {
       e.preventDefault();
       this.fire('editable-content-save', {content: this._newContent});
-    },
+    }
 
     _handleCancel(e) {
       e.preventDefault();
       this.editing = false;
       this.fire('editable-content-cancel');
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditableContent.is, GrEditableContent);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html
index 3f5ccb0..69c9a00 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-editable-content</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -49,6 +49,7 @@
     teardown(() => { sandbox.restore(); });
 
     test('save event', done => {
+      element.content = '';
       element._newContent = 'foo';
       element.addEventListener('editable-content-save', e => {
         assert.equal(e.detail.content, 'foo');
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
index 941b59d..78465e1 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.html
@@ -21,6 +21,7 @@
 <link rel="import" href="/bower_components/paper-input/paper-input.html">
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
 <link rel="import" href="../../../styles/shared-styles.html">
+<link rel="import" href="../gr-button/gr-button.html">
 
 <dom-module id="gr-editable-label">
   <template>
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.js b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.js
index 4485551..b989401 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.js
@@ -20,76 +20,84 @@
   const AWAIT_MAX_ITERS = 10;
   const AWAIT_STEP = 5;
 
-  Polymer({
-    is: 'gr-editable-label',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrEditableLabel extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-editable-label'; }
     /**
      * Fired when the value is changed.
      *
      * @event changed
      */
 
-    properties: {
-      labelText: String,
-      editing: {
-        type: Boolean,
-        value: false,
-      },
-      value: {
-        type: String,
-        notify: true,
-        value: '',
-        observer: '_updateTitle',
-      },
-      placeholder: {
-        type: String,
-        value: '',
-      },
-      readOnly: {
-        type: Boolean,
-        value: false,
-      },
-      uppercase: {
-        type: Boolean,
-        reflectToAttribute: true,
-        value: false,
-      },
-      maxLength: Number,
-      _inputText: String,
-      // This is used to push the iron-input element up on the page, so
-      // the input is placed in approximately the same position as the
-      // trigger.
-      _verticalOffset: {
-        type: Number,
-        readOnly: true,
-        value: -30,
-      },
-    },
+    static get properties() {
+      return {
+        labelText: String,
+        editing: {
+          type: Boolean,
+          value: false,
+        },
+        value: {
+          type: String,
+          notify: true,
+          value: '',
+          observer: '_updateTitle',
+        },
+        placeholder: {
+          type: String,
+          value: '',
+        },
+        readOnly: {
+          type: Boolean,
+          value: false,
+        },
+        uppercase: {
+          type: Boolean,
+          reflectToAttribute: true,
+          value: false,
+        },
+        maxLength: Number,
+        _inputText: String,
+        // This is used to push the iron-input element up on the page, so
+        // the input is placed in approximately the same position as the
+        // trigger.
+        _verticalOffset: {
+          type: Number,
+          readOnly: true,
+          value: -30,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
+    ready() {
+      super.ready();
+      this._ensureAttribute('tabindex', '0');
+    }
 
-    keyBindings: {
-      enter: '_handleEnter',
-      esc: '_handleEsc',
-    },
-
-    hostAttributes: {
-      tabindex: '0',
-    },
+    get keyBindings() {
+      return {
+        enter: '_handleEnter',
+        esc: '_handleEsc',
+      };
+    }
 
     _usePlaceholder(value, placeholder) {
       return (!value || !value.length) && placeholder;
-    },
+    }
 
     _computeLabel(value, placeholder) {
       if (this._usePlaceholder(value, placeholder)) {
         return placeholder;
       }
       return value;
-    },
+    }
 
     _showDropdown() {
       if (this.readOnly || this.editing) { return; }
@@ -98,13 +106,13 @@
         if (!this.$.input.value) { return; }
         this._nativeInput.setSelectionRange(0, this.$.input.value.length);
       });
-    },
+    }
 
     open() {
       return this._open().then(() => {
         this._nativeInput.focus();
       });
-    },
+    }
 
     _open(...args) {
       this.$.dropdown.open();
@@ -115,7 +123,7 @@
         Polymer.IronOverlayBehaviorImpl.open.apply(this.$.dropdown, args);
         this._awaitOpen(resolve);
       });
-    },
+    }
 
     /**
      * NOTE: (wyatta) Slightly hacky way to listen to the overlay actually
@@ -133,11 +141,11 @@
         }, AWAIT_STEP);
       };
       step.call(this);
-    },
+    }
 
     _id() {
       return this.getAttribute('id') || 'global';
-    },
+    }
 
     _save() {
       if (!this.editing) { return; }
@@ -145,20 +153,20 @@
       this.value = this._inputText;
       this.editing = false;
       this.fire('changed', this.value);
-    },
+    }
 
     _cancel() {
       if (!this.editing) { return; }
       this.$.dropdown.close();
       this.editing = false;
       this._inputText = this.value;
-    },
+    }
 
     get _nativeInput() {
       // In Polymer 2, the namespace of nativeInput
       // changed from input to nativeInput
       return this.$.input.$.nativeInput || this.$.input.$.input;
-    },
+    }
 
     _handleEnter(e) {
       e = this.getKeyboardEvent(e);
@@ -167,7 +175,7 @@
         e.preventDefault();
         this._save();
       }
-    },
+    }
 
     _handleEsc(e) {
       e = this.getKeyboardEvent(e);
@@ -176,7 +184,7 @@
         e.preventDefault();
         this._cancel();
       }
-    },
+    }
 
     _computeLabelClass(readOnly, value, placeholder) {
       const classes = [];
@@ -185,10 +193,12 @@
         classes.push('placeholder');
       }
       return classes.join(' ');
-    },
+    }
 
     _updateTitle(value) {
       this.setAttribute('title', this._computeLabel(value, this.placeholder));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrEditableLabel.is, GrEditableLabel);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html
index 416a499..1690c3a 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-editable-label</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel.js b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel.js
index 2c32709..af533bc 100644
--- a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel.js
+++ b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel.js
@@ -17,47 +17,52 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-fixed-panel',
+  class GrFixedPanel extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-fixed-panel'; }
 
-    properties: {
-      floatingDisabled: Boolean,
-      readyForMeasure: {
-        type: Boolean,
-        observer: '_readyForMeasureObserver',
-      },
-      keepOnScroll: {
-        type: Boolean,
-        value: false,
-      },
-      _isMeasured: {
-        type: Boolean,
-        value: false,
-      },
+    static get properties() {
+      return {
+        floatingDisabled: Boolean,
+        readyForMeasure: {
+          type: Boolean,
+          observer: '_readyForMeasureObserver',
+        },
+        keepOnScroll: {
+          type: Boolean,
+          value: false,
+        },
+        _isMeasured: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * Initial offset from the top of the document, in pixels.
        */
-      _topInitial: Number,
+        _topInitial: Number,
 
-      /**
+        /**
        * Current offset from the top of the window, in pixels.
        */
-      _topLast: Number,
+        _topLast: Number,
 
-      _headerHeight: Number,
-      _headerFloating: {
-        type: Boolean,
-        value: false,
-      },
-      _observer: {
-        type: Object,
-        value: null,
-      },
-      _webComponentsReady: Boolean,
-    },
+        _headerHeight: Number,
+        _headerFloating: {
+          type: Boolean,
+          value: false,
+        },
+        _observer: {
+          type: Object,
+          value: null,
+        },
+        _webComponentsReady: Boolean,
+      };
+    }
 
     attached() {
+      super.attached();
       if (this.floatingDisabled) {
         return;
       }
@@ -69,21 +74,22 @@
       this.listen(window, 'scroll', '_updateOnScroll');
       this._observer = new MutationObserver(this.update.bind(this));
       this._observer.observe(this.$.header, {childList: true, subtree: true});
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'scroll', '_updateOnScroll');
       this.unlisten(window, 'resize', 'update');
       if (this._observer) {
         this._observer.disconnect();
       }
-    },
+    }
 
     _readyForMeasureObserver(readyForMeasure) {
       if (readyForMeasure) {
         this.update();
       }
-    },
+    }
 
     _computeHeaderClass(headerFloating, topLast) {
       const fixedAtTop = this.keepOnScroll && topLast === 0;
@@ -91,7 +97,7 @@
         headerFloating ? 'floating' : '',
         fixedAtTop ? 'fixedAtTop' : '',
       ].join(' ');
-    },
+    }
 
     unfloat() {
       if (this.floatingDisabled) {
@@ -100,19 +106,19 @@
       this.$.header.style.top = '';
       this._headerFloating = false;
       this.updateStyles({'--header-height': ''});
-    },
+    }
 
     update() {
       this.debounce('update', () => {
         this._updateDebounced();
       }, 100);
-    },
+    }
 
     _updateOnScroll() {
       this.debounce('update', () => {
         this._updateDebounced();
       });
-    },
+    }
 
     _updateDebounced() {
       if (this.floatingDisabled) {
@@ -121,11 +127,11 @@
       this._isMeasured = false;
       this._maybeFloatHeader();
       this._reposition();
-    },
+    }
 
     _getElementTop() {
       return this.getBoundingClientRect().top;
-    },
+    }
 
     _reposition() {
       if (!this._headerFloating) {
@@ -155,7 +161,7 @@
         }
         this._topLast = newTop;
       }
-    },
+    }
 
     _measure() {
       if (this._isMeasured) {
@@ -171,12 +177,12 @@
       this._topInitial =
         this.getBoundingClientRect().top + document.body.scrollTop;
       this._isMeasured = true;
-    },
+    }
 
     _isFloatingNeeded() {
       return this.keepOnScroll ||
         document.body.scrollWidth > document.body.clientWidth;
-    },
+    }
 
     _maybeFloatHeader() {
       if (!this._isFloatingNeeded()) {
@@ -186,11 +192,13 @@
       if (this._isMeasured) {
         this._floatHeader();
       }
-    },
+    }
 
     _floatHeader() {
       this.updateStyles({'--header-height': this._headerHeight + 'px'});
       this._headerFloating = true;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrFixedPanel.is, GrFixedPanel);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html
index 75e9901..419b3e7 100644
--- a/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-fixed-panel/gr-fixed-panel_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-fixed-panel</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
index 4e68d42..7730a75 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.js
@@ -20,30 +20,37 @@
   // eslint-disable-next-line no-unused-vars
   const QUOTE_MARKER_PATTERN = /\n\s?>\s/g;
 
-  Polymer({
-    is: 'gr-formatted-text',
+  class GrFormattedText extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-formatted-text'; }
 
-    properties: {
-      content: {
-        type: String,
-        observer: '_contentChanged',
-      },
-      config: Object,
-      noTrailingMargin: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        content: {
+          type: String,
+          observer: '_contentChanged',
+        },
+        config: Object,
+        noTrailingMargin: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    observers: [
-      '_contentOrConfigChanged(content, config)',
-    ],
+    static get observers() {
+      return [
+        '_contentOrConfigChanged(content, config)',
+      ];
+    }
 
     ready() {
+      super.ready();
       if (this.noTrailingMargin) {
         this.classList.add('noTrailingMargin');
       }
-    },
+    }
 
     /**
      * Get the plain text as it appears in the generated DOM.
@@ -56,7 +63,7 @@
      */
     getTextContent() {
       return this._blocksToText(this._computeBlocks(this.content));
-    },
+    }
 
     _contentChanged(content) {
       // In the case where the config may not be set (perhaps due to the
@@ -64,7 +71,7 @@
       // prevent waiting on the config to display the text.
       if (this.config) { return; }
       this._contentOrConfigChanged(content);
-    },
+    }
 
     /**
      * Given a source string, update the DOM inside #container.
@@ -81,7 +88,7 @@
       for (const node of this._computeNodes(this._computeBlocks(content))) {
         container.appendChild(node);
       }
-    },
+    }
 
     /**
      * Given a source string, parse into an array of block objects. Each block
@@ -127,7 +134,7 @@
         }
       }
       return result;
-    },
+    }
 
     /**
      * Take a block of comment text that contains a list and potentially
@@ -201,7 +208,7 @@
       if (block !== null) {
         out.push(block);
       }
-    },
+    }
 
     _makeQuote(p) {
       const quotedLines = p
@@ -212,21 +219,21 @@
         type: 'quote',
         blocks: this._computeBlocks(quotedLines),
       };
-    },
+    }
 
     _isQuote(p) {
       return p.startsWith('> ') || p.startsWith(' > ');
-    },
+    }
 
     _isPreFormat(p) {
       return p.includes('\n ') || p.includes('\n\t') ||
           p.startsWith(' ') || p.startsWith('\t');
-    },
+    }
 
     _isList(p) {
       return p.includes('\n- ') || p.includes('\n* ') ||
           p.startsWith('- ') || p.startsWith('* ');
-    },
+    }
 
     /**
      * @param {string} content
@@ -241,7 +248,7 @@
         text.classList.add('pre');
       }
       return text;
-    },
+    }
 
     /**
      * Map an array of block objects to an array of DOM nodes.
@@ -278,7 +285,7 @@
           return ul;
         }
       });
-    },
+    }
 
     _blocksToText(blocks) {
       return blocks.map(block => {
@@ -292,6 +299,8 @@
           return block.items.join('\n');
         }
       }).join('\n\n');
-    },
-  });
+    }
+  }
+
+  customElements.define(GrFormattedText.is, GrFormattedText);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html
index 801190a..92fbc74 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-editable-label</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard.js b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard.js
index 3a43191..5e3cfb3 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard.js
@@ -25,82 +25,90 @@
    */
   const DIAGONAL_OVERFLOW = 15;
 
-  Polymer({
-    is: 'gr-hovercard',
+  class GrHovercard extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-hovercard'; }
 
-    properties: {
+    static get properties() {
+      return {
       /**
        * @type {?}
        */
-      _target: Object,
+        _target: Object,
 
-      /**
+        /**
        * Determines whether or not the hovercard is visible.
        *
        * @type {boolean}
        */
-      _isShowing: {
-        type: Boolean,
-        value: false,
-      },
-      /**
+        _isShowing: {
+          type: Boolean,
+          value: false,
+        },
+        /**
        * The `id` of the element that the hovercard is anchored to.
        *
        * @type {string}
        */
-      for: {
-        type: String,
-        observer: '_forChanged',
-      },
+        for: {
+          type: String,
+          observer: '_forChanged',
+        },
 
-      /**
+        /**
        * The spacing between the top of the hovercard and the element it is
        * anchored to.
        *
        * @type {number}
        */
-      offset: {
-        type: Number,
-        value: 14,
-      },
+        offset: {
+          type: Number,
+          value: 14,
+        },
 
-      /**
+        /**
        * Positions the hovercard to the top, right, bottom, left, bottom-left,
        * bottom-right, top-left, or top-right of its content.
        *
        * @type {string}
        */
-      position: {
-        type: String,
-        value: 'bottom',
-      },
+        position: {
+          type: String,
+          value: 'bottom',
+        },
 
-      container: Object,
-      /**
+        container: Object,
+        /**
        * ID for the container element.
        *
        * @type {string}
        */
-      containerId: {
-        type: String,
-        value: 'gr-hovercard-container',
-      },
-    },
-
-    listeners: {
-      mouseleave: 'hide',
-    },
+        containerId: {
+          type: String,
+          value: 'gr-hovercard-container',
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       if (!this._target) { this._target = this.target; }
       this.listen(this._target, 'mouseenter', 'show');
       this.listen(this._target, 'focus', 'show');
       this.listen(this._target, 'mouseleave', 'hide');
       this.listen(this._target, 'blur', 'hide');
       this.listen(this._target, 'click', 'hide');
-    },
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('mouseleave',
+          e => this.hide(e));
+    }
 
     ready() {
+      super.ready();
       // First, check to see if the container has already been created.
       this.container = Gerrit.getRootElement()
           .querySelector('#' + this.containerId);
@@ -111,7 +119,7 @@
       this.container = document.createElement('div');
       this.container.setAttribute('id', this.containerId);
       Gerrit.getRootElement().appendChild(this.container);
-    },
+    }
 
     removeListeners() {
       this.unlisten(this._target, 'mouseenter', 'show');
@@ -119,7 +127,7 @@
       this.unlisten(this._target, 'mouseleave', 'hide');
       this.unlisten(this._target, 'blur', 'hide');
       this.unlisten(this._target, 'click', 'hide');
-    },
+    }
 
     /**
      * Returns the target element that the hovercard is anchored to (the `id` of
@@ -140,7 +148,7 @@
           parentNode;
       }
       return target;
-    },
+    }
 
     /**
      * Hides/closes the hovercard. This occurs when the user triggers the
@@ -184,7 +192,7 @@
       if (this.container.contains(this)) {
         this.container.removeChild(this);
       }
-    },
+    }
 
     /**
      * Shows/opens the hovercard. This occurs when the user triggers the
@@ -207,7 +215,7 @@
 
       // Trigger the transition
       this.classList.add(HOVER_CLASS);
-    },
+    }
 
     /**
      * Updates the hovercard's position based on the `position` attribute
@@ -306,7 +314,7 @@
       // Set the hovercard's position
       cssText += `left:${hovercardLeft}px; top:${hovercardTop}px;`;
       this.style.cssText = cssText;
-    },
+    }
 
     /**
      * Responds to a change in the `for` value and gets the updated `target`
@@ -316,6 +324,8 @@
      */
     _forChanged() {
       this._target = this.target;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrHovercard.is, GrHovercard);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html
index 8e79f65..35d736c 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-hovercard</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html
index 3223636..66e7a74 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-context_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-annotation-actions-context</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
index 987b551..98ff954 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-annotation-actions-js-api-js-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
index 2d66cfa..0ec3d6a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.js
@@ -50,7 +50,11 @@
       return url.pathname;
     }
     const base = Gerrit.BaseUrlBehavior.getBaseUrl();
-    const pathname = url.pathname.replace(base, '');
+    let pathname = url.pathname.replace(base, '');
+    // Load from ASSETS_PATH
+    if (window.ASSETS_PATH && url.href.includes(window.ASSETS_PATH)) {
+      pathname = url.href.replace(window.ASSETS_PATH, '');
+    }
     // Site theme is server from predefined path.
     if (pathname === '/static/gerrit-theme.html') {
       return 'gerrit-theme';
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html
index 89dfbd7..b43796f 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-api-interface</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -72,6 +72,15 @@
             'gerrit-theme'
         );
       });
+
+      test('with ASSETS_PATH', () => {
+        window.ASSETS_PATH = 'http://cdn.com/2';
+        assert.equal(
+            getPluginNameFromUrl(`${window.ASSETS_PATH}/plugins/a.html`),
+            'a'
+        );
+        window.ASSETS_PATH = undefined;
+      });
     });
   });
 </script>
\ No newline at end of file
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html
index 7332877..cbe2d37 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-actions-js-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-actions-js-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
index 842a2fe..7955aa4 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-change-reply-js-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-change-reply-js-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html
index e81b8aa..7b03308 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-gerrit_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-api-interface</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
index 3206b21..1802a4a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface.js
@@ -37,24 +37,34 @@
     REPLY_DIALOG: 'replydialog',
   };
 
-  Polymer({
-    is: 'gr-js-api-interface',
+  /**
+    * @appliesMixin Gerrit.PatchSetMixin
+    */
+  class GrJsApiInterface extends Polymer.mixinBehaviors( [
+    Gerrit.PatchSetBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-js-api-interface'; }
 
-    properties: {
-      _elements: {
-        type: Object,
-        value: {}, // Shared across all instances.
-      },
-      _eventCallbacks: {
-        type: Object,
-        value: {}, // Shared across all instances.
-      },
-    },
+    constructor() {
+      super();
+      this.Element = Element;
+      this.EventType = EventType;
+    }
 
-    behaviors: [Gerrit.PatchSetBehavior],
-
-    Element,
-    EventType,
+    static get properties() {
+      return {
+        _elements: {
+          type: Object,
+          value: {}, // Shared across all instances.
+        },
+        _eventCallbacks: {
+          type: Object,
+          value: {}, // Shared across all instances.
+        },
+      };
+    }
 
     handleEvent(type, detail) {
       Gerrit.awaitPluginsLoaded().then(() => {
@@ -80,22 +90,22 @@
             break;
         }
       });
-    },
+    }
 
     addElement(key, el) {
       this._elements[key] = el;
-    },
+    }
 
     getElement(key) {
       return this._elements[key];
-    },
+    }
 
     addEventCallback(eventName, callback) {
       if (!this._eventCallbacks[eventName]) {
         this._eventCallbacks[eventName] = [];
       }
       this._eventCallbacks[eventName].push(callback);
-    },
+    }
 
     canSubmitChange(change, revision) {
       const submitCallbacks = this._getEventCallbacks(EventType.SUBMIT_CHANGE);
@@ -109,14 +119,14 @@
       });
 
       return !cancelSubmit;
-    },
+    }
 
     _removeEventCallbacks() {
       for (const k in EventType) {
         if (!EventType.hasOwnProperty(k)) { continue; }
         this._eventCallbacks[EventType[k]] = [];
       }
-    },
+    }
 
     _handleHistory(detail) {
       for (const cb of this._getEventCallbacks(EventType.HISTORY)) {
@@ -126,7 +136,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     _handleShowChange(detail) {
       // Note (issue 8221) Shallow clone the change object and add a mergeable
@@ -161,7 +171,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     handleCommitMessage(change, msg) {
       for (const cb of this._getEventCallbacks(EventType.COMMIT_MSG_EDIT)) {
@@ -171,7 +181,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     _handleComment(detail) {
       for (const cb of this._getEventCallbacks(EventType.COMMENT)) {
@@ -181,7 +191,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     _handleLabelChange(detail) {
       for (const cb of this._getEventCallbacks(EventType.LABEL_CHANGE)) {
@@ -191,7 +201,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     _handleHighlightjsLoaded(detail) {
       for (const cb of this._getEventCallbacks(EventType.HIGHLIGHTJS_LOADED)) {
@@ -201,7 +211,7 @@
           console.error(err);
         }
       }
-    },
+    }
 
     modifyRevertMsg(change, revertMsg, origMsg) {
       for (const cb of this._getEventCallbacks(EventType.REVERT)) {
@@ -212,7 +222,7 @@
         }
       }
       return revertMsg;
-    },
+    }
 
     modifyRevertSubmissionMsg(change, revertSubmissionMsg, origMsg) {
       for (const cb of this._getEventCallbacks(EventType.REVERT_SUBMISSION)) {
@@ -223,7 +233,7 @@
         }
       }
       return revertSubmissionMsg;
-    },
+    }
 
     getDiffLayers(path, changeNum, patchNum) {
       const layers = [];
@@ -237,7 +247,7 @@
         }
       }
       return layers;
-    },
+    }
 
     /**
      * Retrieves coverage data possibly provided by a plugin.
@@ -265,7 +275,7 @@
         }
         return [];
       });
-    },
+    }
 
     getAdminMenuLinks() {
       const links = [];
@@ -274,7 +284,7 @@
         links.push(...adminApi.getMenuLinks());
       }
       return links;
-    },
+    }
 
     getLabelValuesPostRevert(change) {
       let labels = {};
@@ -286,10 +296,12 @@
         }
       }
       return labels;
-    },
+    }
 
     _getEventCallbacks(type) {
       return this._eventCallbacks[type] || [];
-    },
-  });
+    }
+  }
+
+  customElements.define(GrJsApiInterface.is, GrJsApiInterface);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
index ae12940..537e55b 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-api-interface</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html
index 6da117f..f7b7cf8 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-action-context</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html
index 8ed7f14..b39ed6d 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-endpoints_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-endpoints</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
index 4be38b6..96d8411 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.js
@@ -113,7 +113,7 @@
       this._pluginListLoaded = true;
 
       plugins.forEach(path => {
-        const url = this._urlFor(path);
+        const url = this._urlFor(path, window.ASSETS_PATH);
         // Skip if preloaded, for bundling.
         if (this.isPluginPreloaded(url)) return;
 
@@ -128,11 +128,11 @@
         });
 
         if (this._isPathEndsWith(url, '.html')) {
-          this._importHtmlPlugin(url, opts && opts[path]);
+          this._importHtmlPlugin(path, opts && opts[path]);
         } else if (this._isPathEndsWith(url, '.js')) {
-          this._loadJsPlugin(url);
+          this._loadJsPlugin(path);
         } else {
-          this._failToLoad(`Unrecognized plugin url ${url}`, url);
+          this._failToLoad(`Unrecognized plugin path ${path}`, path);
         }
       });
 
@@ -181,14 +181,15 @@
         return;
       }
 
-      const pluginObject = this.getPlugin(src);
+      const url = this._urlFor(src);
+      const pluginObject = this.getPlugin(url);
       let plugin = pluginObject && pluginObject.plugin;
       if (!plugin) {
-        plugin = new Plugin(src);
+        plugin = new Plugin(url);
       }
       try {
         callback(plugin);
-        this._pluginInstalled(src, plugin);
+        this._pluginInstalled(url, plugin);
       } catch (e) {
         this._failToLoad(`${e.name}: ${e.message}`, src);
       }
@@ -313,38 +314,79 @@
     }
 
     _importHtmlPlugin(pluginUrl, opts = {}) {
-      // onload (second param) needs to be a function. When null or undefined
-      // were passed, plugins were not loaded correctly.
+      const urlWithAP = this._urlFor(pluginUrl, window.ASSETS_PATH);
+      const urlWithoutAP = this._urlFor(pluginUrl);
+      let onerror = null;
+      if (urlWithAP !== urlWithoutAP) {
+        onerror = () => this._loadHtmlPlugin(urlWithoutAP, opts.sync);
+      }
+      this._loadHtmlPlugin(urlWithAP, opts.sync, onerror);
+    }
+
+    _loadHtmlPlugin(url, sync, onerror) {
+      if (!onerror) {
+        onerror = () => {
+          this._failToLoad(`${pluginUrl} import error`, pluginUrl);
+        };
+      }
+
       (Polymer.importHref || Polymer.Base.importHref)(
-          this._urlFor(pluginUrl), () => {},
-          () => this._failToLoad(`${pluginUrl} import error`, pluginUrl),
-          !opts.sync);
+          url, () => {},
+          onerror,
+          !sync);
     }
 
     _loadJsPlugin(pluginUrl) {
-      this._createScriptTag(this._urlFor(pluginUrl));
+      const urlWithAP = this._urlFor(pluginUrl, window.ASSETS_PATH);
+      const urlWithoutAP = this._urlFor(pluginUrl);
+      let onerror = null;
+      if (urlWithAP !== urlWithoutAP) {
+        onerror = () => this._createScriptTag(urlWithoutAP);
+      }
+
+      this._createScriptTag(urlWithAP, onerror);
     }
 
-    _createScriptTag(url) {
+    _createScriptTag(url, onerror) {
+      if (!onerror) {
+        onerror = () => this._failToLoad(`${url} load error`, url);
+      }
+
       const el = document.createElement('script');
       el.defer = true;
       el.setAttribute('src', url);
-      el.onerror = () => this._failToLoad(`${url} load error`, url);
+      el.onerror = onerror;
       return document.body.appendChild(el);
     }
 
-    _urlFor(pathOrUrl) {
+    _urlFor(pathOrUrl, assetsPath) {
       if (!pathOrUrl) {
         return pathOrUrl;
       }
+
+      // theme is per host, should always load from assetsPath
+      const isThemeFile = pathOrUrl.endsWith('static/gerrit-theme.html');
+      const shouldTryLoadFromAssetsPathFirst = !isThemeFile && assetsPath;
       if (pathOrUrl.startsWith(PRELOADED_PROTOCOL) ||
           pathOrUrl.startsWith('http')) {
         // Plugins are loaded from another domain or preloaded.
+        if (pathOrUrl.includes(location.host)
+          && shouldTryLoadFromAssetsPathFirst) {
+          // if is loading from host server, try replace with cdn when assetsPath provided
+          return pathOrUrl
+              .replace(location.origin, assetsPath);
+        }
         return pathOrUrl;
       }
+
       if (!pathOrUrl.startsWith('/')) {
         pathOrUrl = '/' + pathOrUrl;
       }
+
+      if (shouldTryLoadFromAssetsPathFirst) {
+        return assetsPath + pathOrUrl;
+      }
+
       return window.location.origin + getBaseUrl() + pathOrUrl;
     }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html
index b0a8c4a..08e7e18 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-host</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
@@ -325,11 +325,11 @@
       let loadJsPluginStub;
       setup(() => {
         importHtmlPluginStub = sandbox.stub();
-        sandbox.stub(Gerrit._pluginLoader, '_importHtmlPlugin', url => {
+        sandbox.stub(Gerrit._pluginLoader, '_loadHtmlPlugin', url => {
           importHtmlPluginStub(url);
         });
         loadJsPluginStub = sandbox.stub();
-        sandbox.stub(Gerrit._pluginLoader, '_loadJsPlugin', url => {
+        sandbox.stub(Gerrit._pluginLoader, '_createScriptTag', url => {
           loadJsPluginStub(url);
         });
       });
@@ -346,8 +346,8 @@
 
         assert.isTrue(failToLoadStub.calledOnce);
         assert.isTrue(failToLoadStub.calledWithExactly(
-            `Unrecognized plugin url ${url}/foo/bar`,
-            `${url}/foo/bar`
+            'Unrecognized plugin path foo/bar',
+            'foo/bar'
         ));
       });
 
@@ -407,6 +407,72 @@
       });
     });
 
+    suite('With ASSETS_PATH', () => {
+      let importHtmlPluginStub;
+      let loadJsPluginStub;
+      setup(() => {
+        window.ASSETS_PATH = 'https://cdn.com';
+        importHtmlPluginStub = sandbox.stub();
+        sandbox.stub(Gerrit._pluginLoader, '_loadHtmlPlugin', url => {
+          importHtmlPluginStub(url);
+        });
+        loadJsPluginStub = sandbox.stub();
+        sandbox.stub(Gerrit._pluginLoader, '_createScriptTag', url => {
+          loadJsPluginStub(url);
+        });
+      });
+
+      teardown(() => {
+        window.ASSETS_PATH = '';
+      });
+
+      test('Should try load plugins from assets path instead', () => {
+        Gerrit._loadPlugins([
+          'foo/bar.js',
+          'foo/bar.html',
+        ]);
+
+        assert.isTrue(importHtmlPluginStub.calledOnce);
+        assert.isTrue(
+            importHtmlPluginStub.calledWithExactly(`https://cdn.com/foo/bar.html`)
+        );
+        assert.isTrue(loadJsPluginStub.calledOnce);
+        assert.isTrue(
+            loadJsPluginStub.calledWithExactly(`https://cdn.com/foo/bar.js`));
+      });
+
+      test('Should honor original path if exists', () => {
+        Gerrit._loadPlugins([
+          'http://e.com/foo/bar.html',
+          'http://e.com/foo/bar.js',
+        ]);
+
+        assert.isTrue(importHtmlPluginStub.calledOnce);
+        assert.isTrue(
+            importHtmlPluginStub.calledWithExactly(`http://e.com/foo/bar.html`)
+        );
+        assert.isTrue(loadJsPluginStub.calledOnce);
+        assert.isTrue(
+            loadJsPluginStub.calledWithExactly(`http://e.com/foo/bar.js`));
+      });
+
+      test('Should try replace current host with assetsPath', () => {
+        const host = window.location.origin;
+        Gerrit._loadPlugins([
+          `${host}/foo/bar.html`,
+          `${host}/foo/bar.js`,
+        ]);
+
+        assert.isTrue(importHtmlPluginStub.calledOnce);
+        assert.isTrue(
+            importHtmlPluginStub.calledWithExactly(`https://cdn.com/foo/bar.html`)
+        );
+        assert.isTrue(loadJsPluginStub.calledOnce);
+        assert.isTrue(
+            loadJsPluginStub.calledWithExactly(`https://cdn.com/foo/bar.js`));
+      });
+    });
+
     test('adds js plugins will call the body', () => {
       Gerrit._loadPlugins([
         'http://e.com/foo/bar.js',
@@ -489,12 +555,10 @@
 
       test('installing preloaded plugin', () => {
         let plugin;
-        window.ASSETS_PATH = 'http://blips.com/chitz';
         Gerrit.install(p => { plugin = p; }, '0.1', 'preloaded:foo');
         assert.strictEqual(plugin.getPluginName(), 'foo');
         assert.strictEqual(plugin.url('/some/thing.html'),
-            'http://blips.com/chitz/plugins/foo/some/thing.html');
-        delete window.ASSETS_PATH;
+            'preloaded:foo/plugins/foo/some/thing.html');
       });
     });
   });
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html
index bcbd961..4aae032 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-rest-api_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-plugin-rest-api</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index 6c306d9..0aaeaa1 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -17,8 +17,6 @@
 (function(window) {
   'use strict';
 
-  const PRELOADED_PROTOCOL = 'preloaded:';
-
   const PANEL_ENDPOINTS_MAPPING = {
     CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK: 'change-view-integration',
     CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK: 'change-metadata-item',
@@ -66,13 +64,6 @@
 
     this._url = new URL(opt_url);
     this._name = getPluginNameFromUrl(this._url);
-    if (this._url.protocol === PRELOADED_PROTOCOL) {
-      // Original plugin URL is used in plugin assets URLs calculation.
-      const assetsBaseUrl = window.ASSETS_PATH ||
-          (window.location.origin + Gerrit.BaseUrlBehavior.getBaseUrl());
-      this._url = new URL(assetsBaseUrl + '/plugins/' + this._name +
-          '/static/' + this._name + '.js');
-    }
   }
 
   Plugin._sharedAPIElement = document.createElement('gr-js-api-interface');
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
index 5461469..b17b251 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
@@ -20,6 +20,7 @@
 <link rel="import" href="../../../styles/gr-voting-styles.html">
 <link rel="import" href="../../../styles/shared-styles.html">
 <link rel="import" href="../gr-account-label/gr-account-label.html">
+<link rel="import" href="../gr-account-chip/gr-account-chip.html">
 <link rel="import" href="../gr-button/gr-button.html">
 <link rel="import" href="../gr-icons/gr-icons.html">
 <link rel="import" href="../gr-label/gr-label.html">
@@ -27,7 +28,9 @@
 
 <dom-module id="gr-label-info">
   <template strip-whitespace>
-    <style include="gr-voting-styles"></style>
+    <style include="gr-voting-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style include="shared-styles">
       .placeholder {
         color: var(--deemphasized-text-color);
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
index 3c27c94..0e529b1 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
@@ -17,17 +17,21 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-label-info',
+  class GrLabelInfo extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-label-info'; }
 
-    properties: {
-      labelInfo: Object,
-      label: String,
-      /** @type {?} */
-      change: Object,
-      account: Object,
-      mutable: Boolean,
-    },
+    static get properties() {
+      return {
+        labelInfo: Object,
+        label: String,
+        /** @type {?} */
+        change: Object,
+        account: Object,
+        mutable: Boolean,
+      };
+    }
 
     /**
      * @param {!Object} labelInfo
@@ -85,7 +89,7 @@
         }
       }
       return result;
-    },
+    }
 
     /**
      * A user is able to delete a vote iff the mutable property is true and the
@@ -106,7 +110,7 @@
         return '';
       }
       return 'hidden';
-    },
+    }
 
     /**
      * Closure annotation for Polymer.prototype.splice is off.
@@ -133,14 +137,14 @@
                 target.disabled = false;
                 return;
               });
-    },
+    }
 
     _computeValueTooltip(labelInfo, score) {
       if (!labelInfo || !labelInfo.values || !labelInfo.values[score]) {
         return '';
       }
       return labelInfo.values[score];
-    },
+    }
 
     /**
      * @param {!Object} labelInfo
@@ -156,6 +160,8 @@
         }
       }
       return '';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLabelInfo.is, GrLabelInfo);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html
index 35dc772..adf88d9 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info_test.html
@@ -17,7 +17,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-label-info</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-label/gr-label.js b/polygerrit-ui/app/elements/shared/gr-label/gr-label.js
index 0de0881..7d82c9c9 100644
--- a/polygerrit-ui/app/elements/shared/gr-label/gr-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-label/gr-label.js
@@ -17,11 +17,16 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-label',
+  /**
+    * @appliesMixin Gerrit.TooltipMixin
+    */
+  class GrLabel extends Polymer.mixinBehaviors( [
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-label'; }
+  }
 
-    behaviors: [
-      Gerrit.TooltipBehavior,
-    ],
-  });
+  customElements.define(GrLabel.is, GrLabel);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.html b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.html
index da0b93f..47be6f7 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.html
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.html
@@ -38,14 +38,7 @@
       #body {
         display: flex;
       }
-      gr-autocomplete {
-        height: 1.5em;
-        --gr-autocomplete: {
-          border: none;
-        }
-      }
       #trigger {
-        border-left: 1px solid var(--deemphasized-text-color);
         color: var(--deemphasized-text-color);
         cursor: pointer;
         padding-left: var(--spacing-s);
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.js b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.js
index fd0f228..d2646af 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.js
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete.js
@@ -17,60 +17,65 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-labeled-autocomplete',
-
+  class GrLabeledAutocomplete extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-labeled-autocomplete'; }
     /**
      * Fired when a value is chosen.
      *
      * @event commit
      */
 
-    properties: {
+    static get properties() {
+      return {
 
-      /**
+        /**
        * Used just like the query property of gr-autocomplete.
        *
        * @type {function(string): Promise<?>}
        */
-      query: {
-        type: Function,
-        value() {
-          return function() {
-            return Promise.resolve([]);
-          };
+        query: {
+          type: Function,
+          value() {
+            return function() {
+              return Promise.resolve([]);
+            };
+          },
         },
-      },
 
-      text: {
-        type: String,
-        value: '',
-        notify: true,
-      },
-      label: String,
-      placeholder: String,
-      disabled: Boolean,
+        text: {
+          type: String,
+          value: '',
+          notify: true,
+        },
+        label: String,
+        placeholder: String,
+        disabled: Boolean,
 
-      _autocompleteThreshold: {
-        type: Number,
-        value: 0,
-        readOnly: true,
-      },
-    },
+        _autocompleteThreshold: {
+          type: Number,
+          value: 0,
+          readOnly: true,
+        },
+      };
+    }
 
     _handleTriggerClick(e) {
       // Stop propagation here so we don't confuse gr-autocomplete, which
       // listens for taps on body to try to determine when it's blurred.
       e.stopPropagation();
       this.$.autocomplete.focus();
-    },
+    }
 
     setText(text) {
       this.$.autocomplete.setText(text);
-    },
+    }
 
     clear() {
       this.setText('');
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLabeledAutocomplete.is, GrLabeledAutocomplete);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html
index b257746..7e8f73f 100644
--- a/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-labeled-autocomplete/gr-labeled-autocomplete_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-labeled-autocomplete</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
index 853a299..1fd122c 100644
--- a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
+++ b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader.js
@@ -20,21 +20,25 @@
   const HLJS_PATH = 'bower_components/highlightjs/highlight.min.js';
   const DARK_THEME_PATH = 'styles/themes/dark-theme.html';
 
-  Polymer({
-    is: 'gr-lib-loader',
+  class GrLibLoader extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-lib-loader'; }
 
-    properties: {
-      _hljsState: {
-        type: Object,
+    static get properties() {
+      return {
+        _hljsState: {
+          type: Object,
 
-        // NOTE: intended singleton.
-        value: {
-          configured: false,
-          loading: false,
-          callbacks: [],
+          // NOTE: intended singleton.
+          value: {
+            configured: false,
+            loading: false,
+            callbacks: [],
+          },
         },
-      },
-    },
+      };
+    }
 
     /**
      * Get the HLJS library. Returns a promise that resolves with a reference to
@@ -59,7 +63,7 @@
 
         this._hljsState.callbacks.push(resolve);
       });
-    },
+    }
 
     /**
      * Loads the dark theme document. Returns a promise that resolves with a
@@ -71,12 +75,15 @@
       return new Promise((resolve, reject) => {
         (this.importHref || Polymer.importHref)(
             this._getLibRoot() + DARK_THEME_PATH, () => {
-              const module = document.createElement('style', 'custom-style');
+              const module = document.createElement('style');
               module.setAttribute('include', 'dark-theme');
-              resolve(module);
+              const cs = document.createElement('custom-style');
+              cs.appendChild(module);
+
+              resolve(cs);
             });
       });
-    },
+    }
 
     /**
      * Execute callbacks awaiting the HLJS lib load.
@@ -91,7 +98,7 @@
         cb(lib);
       }
       this._hljsState.callbacks = [];
-    },
+    }
 
     /**
      * Get the HLJS library, assuming it has been loaded. Configure the library
@@ -106,7 +113,7 @@
         lib.configure({classPrefix: 'gr-diff gr-syntax gr-syntax-'});
       }
       return lib;
-    },
+    }
 
     /**
      * Get the resource path used to load the application. If the application
@@ -118,7 +125,7 @@
         return window.STATIC_RESOURCE_PATH + '/';
       }
       return '/';
-    },
+    }
 
     /**
      * Load and execute a JS file from the lib root.
@@ -140,12 +147,14 @@
         script.onerror = reject;
         Polymer.dom(document.head).appendChild(script);
       });
-    },
+    }
 
     _getHLJSUrl() {
       const root = this._getLibRoot();
       if (!root) { return null; }
       return root + HLJS_PATH;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLibLoader.is, GrLibLoader);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html
index 10d1608..832a558 100644
--- a/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-lib-loader/gr-lib-loader_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-lib-loader</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text.js b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text.js
index 048e4f5..9239866 100644
--- a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text.js
+++ b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text.js
@@ -17,57 +17,63 @@
 (function() {
   'use strict';
 
+  /**
+    * @appliesMixin Gerrit.TooltipMixin
+    */
   /*
    * The gr-limited-text element is for displaying text with a maximum length
    * (in number of characters) to display. If the length of the text exceeds the
    * configured limit, then an ellipsis indicates that the text was truncated
    * and a tooltip containing the full text is enabled.
    */
+  class GrLimitedText extends Polymer.mixinBehaviors( [
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-limited-text'; }
 
-  Polymer({
-    is: 'gr-limited-text',
-
-    properties: {
+    static get properties() {
+      return {
       /** The un-truncated text to display. */
-      text: String,
+        text: String,
 
-      /** The maximum length for the text to display before truncating. */
-      limit: {
-        type: Number,
-        value: null,
-      },
+        /** The maximum length for the text to display before truncating. */
+        limit: {
+          type: Number,
+          value: null,
+        },
 
-      /** Boolean property used by Gerrit.TooltipBehavior. */
-      hasTooltip: {
-        type: Boolean,
-        value: false,
-      },
+        /** Boolean property used by Gerrit.TooltipBehavior. */
+        hasTooltip: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * Disable the tooltip.
        * When set to true, will not show tooltip even text is over limit
        */
-      disableTooltip: {
-        type: Boolean,
-        value: false,
-      },
+        disableTooltip: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * The maximum number of characters to display in the tooltop.
        */
-      tooltipLimit: {
-        type: Number,
-        value: 1024,
-      },
-    },
+        tooltipLimit: {
+          type: Number,
+          value: 1024,
+        },
+      };
+    }
 
-    observers: [
-      '_updateTitle(text, limit, tooltipLimit)',
-    ],
-
-    behaviors: [
-      Gerrit.TooltipBehavior,
-    ],
+    static get observers() {
+      return [
+        '_updateTitle(text, limit, tooltipLimit)',
+      ];
+    }
 
     /**
      * The text or limit have changed. Recompute whether a tooltip needs to be
@@ -85,13 +91,15 @@
       } else {
         this.removeAttribute('title');
       }
-    },
+    }
 
     _computeDisplayText(text, limit) {
       if (!!limit && !!text && text.length > limit) {
         return text.substr(0, limit - 1) + '…';
       }
       return text;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLimitedText.is, GrLimitedText);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html
index 7946bb6..3ba30d1 100644
--- a/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-limited-text/gr-limited-text_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-limited-text</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.js b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.js
index 33a9c25..aaae3d1 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.js
+++ b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.js
@@ -17,41 +17,48 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-linked-chip',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrLinkedChip extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-linked-chip'; }
 
-    properties: {
-      href: String,
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      removable: {
-        type: Boolean,
-        value: false,
-      },
-      text: String,
-      transparentBackground: {
-        type: Boolean,
-        value: false,
-      },
+    static get properties() {
+      return {
+        href: String,
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        removable: {
+          type: Boolean,
+          value: false,
+        },
+        text: String,
+        transparentBackground: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**  If provided, sets the maximum length of the content. */
-      limit: Number,
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
+        /**  If provided, sets the maximum length of the content. */
+        limit: Number,
+      };
+    }
 
     _getBackgroundClass(transparent) {
       return transparent ? 'transparentBackground' : '';
-    },
+    }
 
     _handleRemoveTap(e) {
       e.preventDefault();
       this.fire('remove');
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLinkedChip.is, GrLinkedChip);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html
index 22a2eaf..733e897 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-linked-chip</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text.js b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text.js
index e7247b9..25f406e 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text.js
+++ b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text.js
@@ -17,31 +17,37 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-linked-text',
+  class GrLinkedText extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-linked-text'; }
 
-    properties: {
-      removeZeroWidthSpace: Boolean,
-      content: {
-        type: String,
-        observer: '_contentChanged',
-      },
-      pre: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      disabled: {
-        type: Boolean,
-        value: false,
-        reflectToAttribute: true,
-      },
-      config: Object,
-    },
+    static get properties() {
+      return {
+        removeZeroWidthSpace: Boolean,
+        content: {
+          type: String,
+          observer: '_contentChanged',
+        },
+        pre: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        disabled: {
+          type: Boolean,
+          value: false,
+          reflectToAttribute: true,
+        },
+        config: Object,
+      };
+    }
 
-    observers: [
-      '_contentOrConfigChanged(content, config)',
-    ],
+    static get observers() {
+      return [
+        '_contentOrConfigChanged(content, config)',
+      ];
+    }
 
     _contentChanged(content) {
       // In the case where the config may not be set (perhaps due to the
@@ -49,7 +55,7 @@
       // prevent waiting on the config to display the text.
       if (this.config != null) { return; }
       this.$.output.textContent = content;
-    },
+    }
 
     /**
      * Because either the source text or the linkification config has changed,
@@ -74,7 +80,7 @@
         anchor.setAttribute('target', '_blank');
         anchor.setAttribute('rel', 'noopener');
       });
-    },
+    }
 
     /**
      * This method is called when the GrLikTextParser emits a partial result
@@ -100,6 +106,8 @@
       } else if (fragment) {
         output.appendChild(fragment);
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrLinkedText.is, GrLinkedText);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html
index f01a75c..e9477bf 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-linked-text/gr-linked-text_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-linked-text</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.html b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.html
index a4f75da..a707e35 100644
--- a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.html
+++ b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.html
@@ -16,6 +16,7 @@
 -->
 <link rel="import" href="/bower_components/polymer/polymer.html">
 <link rel="import" href="/bower_components/iron-input/iron-input.html">
+<link rel="import" href="/bower_components/iron-icon/iron-icon.html">
 
 <link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
 <link rel="import" href="../../../behaviors/fire-behavior/fire-behavior.html">
diff --git a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.js b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.js
index 8d81030..9d5d8f5 100644
--- a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.js
+++ b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.js
@@ -19,31 +19,39 @@
 
   const REQUEST_DEBOUNCE_INTERVAL_MS = 200;
 
-  Polymer({
-    is: 'gr-list-view',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrListView extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-list-view'; }
 
-    properties: {
-      createNew: Boolean,
-      items: Array,
-      itemsPerPage: Number,
-      filter: {
-        type: String,
-        observer: '_filterChanged',
-      },
-      offset: Number,
-      loading: Boolean,
-      path: String,
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+    static get properties() {
+      return {
+        createNew: Boolean,
+        items: Array,
+        itemsPerPage: Number,
+        filter: {
+          type: String,
+          observer: '_filterChanged',
+        },
+        offset: Number,
+        loading: Boolean,
+        path: String,
+      };
+    }
 
     detached() {
+      super.detached();
       this.cancelDebouncer('reload');
-    },
+    }
 
     _filterChanged(newFilter, oldFilter) {
       if (!newFilter && !oldFilter) {
@@ -51,7 +59,7 @@
       }
 
       this._debounceReload(newFilter);
-    },
+    }
 
     _debounceReload(filter) {
       this.debounce('reload', () => {
@@ -61,11 +69,11 @@
         }
         page.show(this.path);
       }, REQUEST_DEBOUNCE_INTERVAL_MS);
-    },
+    }
 
     _createNewItem() {
       this.fire('create-clicked');
-    },
+    }
 
     _computeNavLink(offset, direction, itemsPerPage, filter, path) {
       // Offset could be a string when passed from the router.
@@ -79,15 +87,15 @@
         href += ',' + newOffset;
       }
       return href;
-    },
+    }
 
     _computeCreateClass(createNew) {
       return createNew ? 'show' : '';
-    },
+    }
 
     _hidePrevArrow(loading, offset) {
       return loading || offset === 0;
-    },
+    }
 
     _hideNextArrow(loading, items) {
       if (loading || !items || !items.length) {
@@ -95,6 +103,8 @@
       }
       const lastPage = items.length < this.itemsPerPage + 1;
       return lastPage;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrListView.is, GrListView);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html
index c67d8b2..8f87b38 100644
--- a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-list-view</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 <script src="/bower_components/page/page.js"></script>
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
index 8623458..9c7e680 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.js
@@ -21,9 +21,16 @@
   const AWAIT_STEP = 5;
   const BREAKPOINT_FULLSCREEN_OVERLAY = '50em';
 
-  Polymer({
-    is: 'gr-overlay',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrOverlay extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Polymer.IronOverlayBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-overlay'; }
     /**
      * Fired when a fullscreen overlay is closed
      *
@@ -36,22 +43,22 @@
      * @event fullscreen-overlay-opened
      */
 
-    properties: {
-      _fullScreenOpen: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        _fullScreenOpen: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Polymer.IronOverlayBehavior,
-    ],
-
-    listeners: {
-      'iron-overlay-closed': '_close',
-      'iron-overlay-cancelled': '_close',
-    },
+    created() {
+      super.created();
+      this.addEventListener('iron-overlay-closed',
+          () => this._close());
+      this.addEventListener('iron-overlay-cancelled',
+          () => this._close());
+    }
 
     open(...args) {
       return new Promise(resolve => {
@@ -62,18 +69,18 @@
         }
         this._awaitOpen(resolve);
       });
-    },
+    }
 
     _isMobile() {
       return window.matchMedia(`(max-width: ${BREAKPOINT_FULLSCREEN_OVERLAY})`);
-    },
+    }
 
     _close() {
       if (this._fullScreenOpen) {
         this.fire('fullscreen-overlay-closed');
         this._fullScreenOpen = false;
       }
-    },
+    }
 
     /**
      * Override the focus stops that iron-overlay-behavior tries to find.
@@ -81,7 +88,7 @@
     setFocusStops(stops) {
       this.__firstFocusableNode = stops.start;
       this.__lastFocusableNode = stops.end;
-    },
+    }
 
     /**
      * NOTE: (wyatta) Slightly hacky way to listen to the overlay actually
@@ -99,10 +106,12 @@
         }, AWAIT_STEP);
       };
       step.call(this);
-    },
+    }
 
     _id() {
       return this.getAttribute('id') || 'global';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrOverlay.is, GrOverlay);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html
index 08b7497..659823f 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-overlay</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
index 2e05607..23389ee 100644
--- a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
+++ b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav.js
@@ -17,20 +17,26 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-page-nav',
+  class GrPageNav extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-page-nav'; }
 
-    properties: {
-      _headerHeight: Number,
-    },
+    static get properties() {
+      return {
+        _headerHeight: Number,
+      };
+    }
 
     attached() {
+      super.attached();
       this.listen(window, 'scroll', '_handleBodyScroll');
-    },
+    }
 
     detached() {
+      super.detached();
       this.unlisten(window, 'scroll', '_handleBodyScroll');
-    },
+    }
 
     _handleBodyScroll() {
       if (this._headerHeight === undefined) {
@@ -45,20 +51,22 @@
 
       this.$.nav.classList.toggle('pinned',
           this._getScrollY() >= this._headerHeight);
-    },
+    }
 
     /* Functions used for test purposes */
     _getOffsetParent(element) {
       if (!element || !element.offsetParent) { return ''; }
       return element.offsetParent;
-    },
+    }
 
     _getOffsetTop(element) {
       return element.offsetTop;
-    },
+    }
 
     _getScrollY() {
       return window.scrollY;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrPageNav.is, GrPageNav);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html
index b384b47..663d3bd 100644
--- a/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-page-nav/gr-page-nav_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-page-nav</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/page/page.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker.js b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker.js
index e2298c3..47979f1 100644
--- a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker.js
+++ b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker.js
@@ -20,47 +20,54 @@
   const SUGGESTIONS_LIMIT = 15;
   const REF_PREFIX = 'refs/heads/';
 
-  Polymer({
-    is: 'gr-repo-branch-picker',
+  /**
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrRepoBranchPicker extends Polymer.mixinBehaviors( [
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-repo-branch-picker'; }
 
-    properties: {
-      repo: {
-        type: String,
-        notify: true,
-        observer: '_repoChanged',
-      },
-      branch: {
-        type: String,
-        notify: true,
-      },
-      _branchDisabled: Boolean,
-      _query: {
-        type: Function,
-        value() {
-          return this._getRepoBranchesSuggestions.bind(this);
+    static get properties() {
+      return {
+        repo: {
+          type: String,
+          notify: true,
+          observer: '_repoChanged',
         },
-      },
-      _repoQuery: {
-        type: Function,
-        value() {
-          return this._getRepoSuggestions.bind(this);
+        branch: {
+          type: String,
+          notify: true,
         },
-      },
-    },
-
-    behaviors: [
-      Gerrit.URLEncodingBehavior,
-    ],
+        _branchDisabled: Boolean,
+        _query: {
+          type: Function,
+          value() {
+            return this._getRepoBranchesSuggestions.bind(this);
+          },
+        },
+        _repoQuery: {
+          type: Function,
+          value() {
+            return this._getRepoSuggestions.bind(this);
+          },
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       if (this.repo) {
         this.$.repoInput.setText(this.repo);
       }
-    },
+    }
 
     ready() {
+      super.ready();
       this._branchDisabled = !this.repo;
-    },
+    }
 
     _getRepoBranchesSuggestions(input) {
       if (!this.repo) { return Promise.resolve([]); }
@@ -69,19 +76,19 @@
       }
       return this.$.restAPI.getRepoBranches(input, this.repo, SUGGESTIONS_LIMIT)
           .then(this._branchResponseToSuggestions.bind(this));
-    },
+    }
 
     _getRepoSuggestions(input) {
       return this.$.restAPI.getRepos(input, SUGGESTIONS_LIMIT)
           .then(this._repoResponseToSuggestions.bind(this));
-    },
+    }
 
     _repoResponseToSuggestions(res) {
       return res.map(repo => ({
         name: repo.name,
         value: this.singleDecodeURL(repo.id),
       }));
-    },
+    }
 
     _branchResponseToSuggestions(res) {
       return Object.keys(res).map(key => {
@@ -91,19 +98,21 @@
         }
         return {name: branch, value: branch};
       });
-    },
+    }
 
     _repoCommitted(e) {
       this.repo = e.detail.value;
-    },
+    }
 
     _branchCommitted(e) {
       this.branch = e.detail.value;
-    },
+    }
 
     _repoChanged() {
       this.$.branchInput.clear();
       this._branchDisabled = !this.repo;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoBranchPicker.is, GrRepoBranchPicker);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html
index 1ed9151..e7252d6 100644
--- a/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-repo-branch-picker/gr-repo-branch-picker_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-repo-branch-picker</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
index dc07d0f..6c5c150 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-auth_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-auth</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html
index 76c8c2c..623ea18 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-etag-decorator_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-etag-decorator</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index b72f47c..eae25ae 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -39,16 +39,21 @@
   const ANONYMIZED_REVISION_BASE_URL = ANONYMIZED_CHANGE_BASE_URL +
       '/revisions/*';
 
-  Polymer({
-    is: 'gr-rest-api-interface',
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.PathListBehavior,
-      Gerrit.PatchSetBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.PathListMixin
+    * @appliesMixin Gerrit.PatchSetMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrRestApiInterface extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.PathListBehavior,
+    Gerrit.PatchSetBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-rest-api-interface'; }
     /**
      * Fired when an server error occurs.
      *
@@ -73,43 +78,49 @@
      * @event rpc-log
      */
 
-    properties: {
-      _cache: {
-        type: Object,
-        value: new SiteBasedCache(), // Shared across instances.
-      },
-      _credentialCheck: {
-        type: Object,
-        value: {checking: false}, // Shared across instances.
-      },
-      _sharedFetchPromises: {
-        type: Object,
-        value: new FetchPromisesCache(), // Shared across instances.
-      },
-      _pendingRequests: {
-        type: Object,
-        value: {}, // Intentional to share the object across instances.
-      },
-      _etags: {
-        type: Object,
-        value: new GrEtagDecorator(), // Share across instances.
-      },
-      /**
+    constructor() {
+      super();
+      this.JSON_PREFIX = JSON_PREFIX;
+    }
+
+    static get properties() {
+      return {
+        _cache: {
+          type: Object,
+          value: new SiteBasedCache(), // Shared across instances.
+        },
+        _credentialCheck: {
+          type: Object,
+          value: {checking: false}, // Shared across instances.
+        },
+        _sharedFetchPromises: {
+          type: Object,
+          value: new FetchPromisesCache(), // Shared across instances.
+        },
+        _pendingRequests: {
+          type: Object,
+          value: {}, // Intentional to share the object across instances.
+        },
+        _etags: {
+          type: Object,
+          value: new GrEtagDecorator(), // Share across instances.
+        },
+        /**
        * Used to maintain a mapping of changeNums to project names.
        */
-      _projectLookup: {
-        type: Object,
-        value: {}, // Intentional to share the object across instances.
-      },
-      _auth: {
-        type: Object,
-        value: Gerrit.Auth, // Share across instances.
-      },
-    },
-
-    JSON_PREFIX,
+        _projectLookup: {
+          type: Object,
+          value: {}, // Intentional to share the object across instances.
+        },
+        _auth: {
+          type: Object,
+          value: Gerrit.Auth, // Share across instances.
+        },
+      };
+    }
 
     created() {
+      super.created();
       /* Polymer 1 and Polymer 2 have slightly different lifecycle.
       * Differences are not very well documented (see
       * https://github.com/Polymer/old-docs-site/issues/2322).
@@ -130,12 +141,13 @@
       //
 
       this._initRestApiHelper();
-    },
+    }
 
     ready() {
+      super.ready();
       // See comments in created()
       this._initRestApiHelper();
-    },
+    }
 
     _initRestApiHelper() {
       if (this._restApiHelper) {
@@ -146,12 +158,12 @@
         this._restApiHelper = new GrRestApiHelper(this._cache, this._auth,
             this._sharedFetchPromises, this._credentialCheck, this);
       }
-    },
+    }
 
     _fetchSharedCacheURL(req) {
       // Cache is shared across instances
       return this._restApiHelper.fetchCacheURL(req);
-    },
+    }
 
     /**
      * @param {!Object} response
@@ -159,7 +171,7 @@
      */
     getResponseObject(response) {
       return this._restApiHelper.getResponseObject(response);
-    },
+    }
 
     getConfig(noCache) {
       if (!noCache) {
@@ -173,7 +185,7 @@
         url: '/config/server/info',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getRepo(repo, opt_errFn) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -183,7 +195,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*',
       });
-    },
+    }
 
     getProjectConfig(repo, opt_errFn) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -193,7 +205,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/config',
       });
-    },
+    }
 
     getRepoAccess(repo) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -202,7 +214,7 @@
         url: '/access/?project=' + encodeURIComponent(repo),
         anonymizedUrl: '/access/?project=*',
       });
-    },
+    }
 
     getRepoDashboards(repo, opt_errFn) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -212,7 +224,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/dashboards?inherited',
       });
-    },
+    }
 
     saveRepoConfig(repo, config, opt_errFn) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -226,7 +238,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/config',
       });
-    },
+    }
 
     runRepoGC(repo, opt_errFn) {
       if (!repo) { return ''; }
@@ -240,7 +252,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/gc',
       });
-    },
+    }
 
     /**
      * @param {?Object} config
@@ -258,7 +270,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*',
       });
-    },
+    }
 
     /**
      * @param {?Object} config
@@ -274,7 +286,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/groups/*',
       });
-    },
+    }
 
     getGroupConfig(group, opt_errFn) {
       return this._restApiHelper.fetchJSON({
@@ -282,7 +294,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/groups/*/detail',
       });
-    },
+    }
 
     /**
      * @param {string} repo
@@ -302,7 +314,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/branches/*',
       });
-    },
+    }
 
     /**
      * @param {string} repo
@@ -322,7 +334,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/tags/*',
       });
-    },
+    }
 
     /**
      * @param {string} name
@@ -343,7 +355,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/branches/*',
       });
-    },
+    }
 
     /**
      * @param {string} name
@@ -364,7 +376,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/tags/*',
       });
-    },
+    }
 
     /**
      * @param {!string} groupName
@@ -378,7 +390,7 @@
       };
       return this._fetchSharedCacheURL(req)
           .then(configs => configs.hasOwnProperty(groupName));
-    },
+    }
 
     getGroupMembers(groupName, opt_errFn) {
       const encodeName = encodeURIComponent(groupName);
@@ -387,14 +399,14 @@
         errFn: opt_errFn,
         anonymizedUrl: '/groups/*/members',
       });
-    },
+    }
 
     getIncludedGroup(groupName) {
       return this._restApiHelper.fetchJSON({
         url: `/groups/${encodeURIComponent(groupName)}/groups/`,
         anonymizedUrl: '/groups/*/groups',
       });
-    },
+    }
 
     saveGroupName(groupId, name) {
       const encodeId = encodeURIComponent(groupId);
@@ -404,7 +416,7 @@
         body: {name},
         anonymizedUrl: '/groups/*/name',
       });
-    },
+    }
 
     saveGroupOwner(groupId, ownerId) {
       const encodeId = encodeURIComponent(groupId);
@@ -414,7 +426,7 @@
         body: {owner: ownerId},
         anonymizedUrl: '/groups/*/owner',
       });
-    },
+    }
 
     saveGroupDescription(groupId, description) {
       const encodeId = encodeURIComponent(groupId);
@@ -424,7 +436,7 @@
         body: {description},
         anonymizedUrl: '/groups/*/description',
       });
-    },
+    }
 
     saveGroupOptions(groupId, options) {
       const encodeId = encodeURIComponent(groupId);
@@ -434,7 +446,7 @@
         body: options,
         anonymizedUrl: '/groups/*/options',
       });
-    },
+    }
 
     getGroupAuditLog(group, opt_errFn) {
       return this._fetchSharedCacheURL({
@@ -442,7 +454,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/groups/*/log.audit',
       });
-    },
+    }
 
     saveGroupMembers(groupName, groupMembers) {
       const encodeName = encodeURIComponent(groupName);
@@ -453,7 +465,7 @@
         parseResponse: true,
         anonymizedUrl: '/groups/*/members/*',
       });
-    },
+    }
 
     saveIncludedGroup(groupName, includedGroup, opt_errFn) {
       const encodeName = encodeURIComponent(groupName);
@@ -469,7 +481,7 @@
           return this.getResponseObject(response);
         }
       });
-    },
+    }
 
     deleteGroupMembers(groupName, groupMembers) {
       const encodeName = encodeURIComponent(groupName);
@@ -479,7 +491,7 @@
         url: `/groups/${encodeName}/members/${encodeMember}`,
         anonymizedUrl: '/groups/*/members/*',
       });
-    },
+    }
 
     deleteIncludedGroup(groupName, includedGroup) {
       const encodeName = encodeURIComponent(groupName);
@@ -489,14 +501,14 @@
         url: `/groups/${encodeName}/groups/${encodeIncludedGroup}`,
         anonymizedUrl: '/groups/*/groups/*',
       });
-    },
+    }
 
     getVersion() {
       return this._fetchSharedCacheURL({
         url: '/config/server/version',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getDiffPreferences() {
       return this.getLoggedIn().then(loggedIn => {
@@ -527,7 +539,7 @@
           theme: 'DEFAULT',
         });
       });
-    },
+    }
 
     getEditPreferences() {
       return this.getLoggedIn().then(loggedIn => {
@@ -558,7 +570,7 @@
           theme: 'DEFAULT',
         });
       });
-    },
+    }
 
     /**
      * @param {?Object} prefs
@@ -578,7 +590,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {?Object} prefs
@@ -594,7 +606,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {?Object} prefs
@@ -610,7 +622,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getAccount() {
       return this._fetchSharedCacheURL({
@@ -622,7 +634,7 @@
           }
         },
       });
-    },
+    }
 
     getAvatarChangeUrl() {
       return this._fetchSharedCacheURL({
@@ -634,14 +646,14 @@
           }
         },
       });
-    },
+    }
 
     getExternalIds() {
       return this._restApiHelper.fetchJSON({
         url: '/accounts/self/external.ids',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     deleteAccountIdentity(id) {
       return this._restApiHelper.send({
@@ -651,7 +663,7 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} userId the ID of the user usch as an email address.
@@ -662,14 +674,14 @@
         url: `/accounts/${encodeURIComponent(userId)}/detail`,
         anonymizedUrl: '/accounts/*/detail',
       });
-    },
+    }
 
     getAccountEmails() {
       return this._fetchSharedCacheURL({
         url: '/accounts/self/emails',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} email
@@ -682,7 +694,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/account/self/emails/*',
       });
-    },
+    }
 
     /**
      * @param {string} email
@@ -695,7 +707,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/accounts/self/email/*',
       });
-    },
+    }
 
     /**
      * @param {string} email
@@ -724,7 +736,7 @@
           this._cache.set('/accounts/self/emails', emails);
         }
       });
-    },
+    }
 
     /**
      * @param {?Object} obj
@@ -738,7 +750,7 @@
         this._cache.set('/accounts/self/detail',
             Object.assign({}, cachedAccount, obj));
       }
-    },
+    }
 
     /**
      * @param {string} name
@@ -755,7 +767,7 @@
       };
       return this._restApiHelper.send(req)
           .then(newName => this._updateCachedAccount({name: newName}));
-    },
+    }
 
     /**
      * @param {string} username
@@ -772,7 +784,7 @@
       };
       return this._restApiHelper.send(req)
           .then(newName => this._updateCachedAccount({username: newName}));
-    },
+    }
 
     /**
      * @param {string} status
@@ -789,28 +801,28 @@
       };
       return this._restApiHelper.send(req)
           .then(newStatus => this._updateCachedAccount({status: newStatus}));
-    },
+    }
 
     getAccountStatus(userId) {
       return this._restApiHelper.fetchJSON({
         url: `/accounts/${encodeURIComponent(userId)}/status`,
         anonymizedUrl: '/accounts/*/status',
       });
-    },
+    }
 
     getAccountGroups() {
       return this._restApiHelper.fetchJSON({
         url: '/accounts/self/groups',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getAccountAgreements() {
       return this._restApiHelper.fetchJSON({
         url: '/accounts/self/agreements',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     saveAccountAgreement(name) {
       return this._restApiHelper.send({
@@ -819,7 +831,7 @@
         body: name,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string=} opt_params
@@ -835,7 +847,7 @@
         url: '/accounts/self/capabilities' + queryString,
         anonymizedUrl: '/accounts/self/capabilities?q=*',
       });
-    },
+    }
 
     getLoggedIn() {
       return this.getAccount().then(account => {
@@ -843,7 +855,7 @@
       }).catch(() => {
         return false;
       });
-    },
+    }
 
     getIsAdmin() {
       return this.getLoggedIn().then(isLoggedIn => {
@@ -855,18 +867,18 @@
       }).then(capabilities => {
         return capabilities && capabilities.administrateServer;
       });
-    },
+    }
 
     checkCredentials() {
       return this._restApiHelper.checkCredentials();
-    },
+    }
 
     getDefaultPreferences() {
       return this._fetchSharedCacheURL({
         url: '/config/server/preferences',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getPreferences() {
       return this.getLoggedIn().then(loggedIn => {
@@ -892,14 +904,14 @@
           size_bar_in_change_table: true,
         });
       });
-    },
+    }
 
     getWatchedProjects() {
       return this._fetchSharedCacheURL({
         url: '/accounts/self/watched.projects',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} projects
@@ -914,7 +926,7 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} projects
@@ -928,11 +940,11 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     _isNarrowScreen() {
       return window.innerWidth < MAX_UNIFIED_DEFAULT_WINDOW_WIDTH_PX;
-    },
+    }
 
     /**
      * @param {number=} opt_changesPerPage
@@ -988,7 +1000,7 @@
         }
         return response;
       });
-    },
+    }
 
     /**
      * Inserts a change into _projectLookup iff it has a valid structure.
@@ -998,7 +1010,7 @@
       if (change && change.project && change._number) {
         this.setInProjectLookup(change._number, change.project);
       }
-    },
+    }
 
     /**
      * TODO (beckysiegel) this needs to be rewritten with the optional param
@@ -1012,7 +1024,7 @@
     getChangeActionURL(changeNum, opt_patchNum, endpoint) {
       return this._changeBaseURL(changeNum, opt_patchNum)
           .then(url => url + endpoint);
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1043,7 +1055,7 @@
             changeNum, optionsHex, opt_errFn, opt_cancelCondition)
             .then(GrReviewerUpdatesParser.parse);
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1059,7 +1071,7 @@
       );
       return this._getChangeDetail(changeNum, optionsHex, opt_errFn,
           opt_cancelCondition);
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1109,7 +1121,7 @@
           });
         });
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1122,7 +1134,7 @@
         patchNum,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1143,7 +1155,7 @@
         params,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1161,7 +1173,7 @@
         endpoint,
         anonymizedEndpoint,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1176,7 +1188,7 @@
         patchNum,
         anonymizedEndpoint: '/files?q=*',
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1189,7 +1201,7 @@
           res.files);
       }
       return this.getChangeFiles(changeNum, patchRange);
-    },
+    }
 
     /**
      * The closure compiler doesn't realize this.specialFilePathCompare is
@@ -1201,7 +1213,7 @@
         if (!files) return;
         return Object.keys(files).sort(this.specialFilePathCompare);
       });
-    },
+    }
 
     getChangeRevisionActions(changeNum, patchNum) {
       const req = {
@@ -1219,7 +1231,7 @@
         }
         return revisionActions;
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1229,7 +1241,7 @@
     getChangeSuggestedReviewers(changeNum, inputVal, opt_errFn) {
       return this._getChangeSuggestedGroup('REVIEWER', changeNum, inputVal,
           opt_errFn);
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1239,7 +1251,7 @@
     getChangeSuggestedCCs(changeNum, inputVal, opt_errFn) {
       return this._getChangeSuggestedGroup('CC', changeNum, inputVal,
           opt_errFn);
-    },
+    }
 
     _getChangeSuggestedGroup(reviewerState, changeNum, inputVal, opt_errFn) {
       // More suggestions may obscure content underneath in the reply dialog,
@@ -1253,7 +1265,7 @@
         params,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1264,7 +1276,7 @@
         endpoint: '/in',
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     _computeFilter(filter) {
       if (filter && filter.startsWith('^')) {
@@ -1275,7 +1287,7 @@
         filter = '';
       }
       return filter;
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1287,7 +1299,7 @@
 
       return `/groups/?n=${groupsPerPage + 1}&S=${offset}` +
         this._computeFilter(filter);
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1323,15 +1335,15 @@
 
       return `/projects/?n=${reposPerPage + 1}&S=${offset}` +
         `&query=${encodedFilter}`;
-    },
+    }
 
     invalidateGroupsCache() {
       this._restApiHelper.invalidateFetchPromisesPrefix('/groups/?');
-    },
+    }
 
     invalidateReposCache() {
       this._restApiHelper.invalidateFetchPromisesPrefix('/projects/?');
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1346,7 +1358,7 @@
         url,
         anonymizedUrl: '/groups/?*',
       });
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1363,7 +1375,7 @@
         url,
         anonymizedUrl: '/projects/?*',
       });
-    },
+    }
 
     setRepoHead(repo, ref) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -1374,7 +1386,7 @@
         body: {ref},
         anonymizedUrl: '/projects/*/HEAD',
       });
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1397,7 +1409,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/branches?*',
       });
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1421,7 +1433,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/tags',
       });
-    },
+    }
 
     /**
      * @param {string} filter
@@ -1440,7 +1452,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/plugins/?all',
       });
-    },
+    }
 
     getRepoAccessRights(repoName, opt_errFn) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -1450,7 +1462,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/access',
       });
-    },
+    }
 
     setRepoAccessRights(repoName, repoInfo) {
       // TODO(kaspern): Rename rest api from /projects/ to /repos/ once backend
@@ -1461,7 +1473,7 @@
         body: repoInfo,
         anonymizedUrl: '/projects/*/access',
       });
-    },
+    }
 
     setRepoAccessRightsForReview(projectName, projectInfo) {
       return this._restApiHelper.send({
@@ -1471,7 +1483,7 @@
         parseResponse: true,
         anonymizedUrl: '/projects/*/access:review',
       });
-    },
+    }
 
     /**
      * @param {string} inputVal
@@ -1487,7 +1499,7 @@
         params,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} inputVal
@@ -1507,7 +1519,7 @@
         params,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {string} inputVal
@@ -1526,15 +1538,15 @@
         params,
         anonymizedUrl: '/accounts/?n=*',
       });
-    },
+    }
 
     addChangeReviewer(changeNum, reviewerID) {
       return this._sendChangeReviewerRequest('POST', changeNum, reviewerID);
-    },
+    }
 
     removeChangeReviewer(changeNum, reviewerID) {
       return this._sendChangeReviewerRequest('DELETE', changeNum, reviewerID);
-    },
+    }
 
     _sendChangeReviewerRequest(method, changeNum, reviewerID) {
       return this.getChangeActionURL(changeNum, null, '/reviewers')
@@ -1553,7 +1565,7 @@
 
             return this._restApiHelper.send({method, url, body});
           });
-    },
+    }
 
     getRelatedChanges(changeNum, patchNum) {
       return this._getChangeURLAndFetch({
@@ -1562,7 +1574,7 @@
         patchNum,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     getChangesSubmittedTogether(changeNum) {
       return this._getChangeURLAndFetch({
@@ -1570,7 +1582,7 @@
         endpoint: '/submitted_together?o=NON_VISIBLE_CHANGES',
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     getChangeConflicts(changeNum) {
       const options = this.listChangesOptionsToHex(
@@ -1579,14 +1591,14 @@
       );
       const params = {
         O: options,
-        q: 'status:open is:mergeable conflicts:' + changeNum,
+        q: 'status:open conflicts:' + changeNum,
       };
       return this._restApiHelper.fetchJSON({
         url: '/changes/',
         params,
         anonymizedUrl: '/changes/conflicts:*',
       });
-    },
+    }
 
     getChangeCherryPicks(project, changeID, changeNum) {
       const options = this.listChangesOptionsToHex(
@@ -1608,7 +1620,7 @@
         params,
         anonymizedUrl: '/changes/change:*',
       });
-    },
+    }
 
     getChangesWithSameTopic(topic, changeNum) {
       const options = this.listChangesOptionsToHex(
@@ -1631,7 +1643,7 @@
         params,
         anonymizedUrl: '/changes/topic:*',
       });
-    },
+    }
 
     getReviewedFiles(changeNum, patchNum) {
       return this._getChangeURLAndFetch({
@@ -1640,7 +1652,7 @@
         patchNum,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1658,7 +1670,7 @@
         errFn: opt_errFn,
         anonymizedEndpoint: '/files/*/reviewed',
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1679,7 +1691,7 @@
           errFn: opt_errFn,
         });
       });
-    },
+    }
 
     getChangeEdit(changeNum, opt_download_commands) {
       const params = opt_download_commands ? {'download-commands': true} : null;
@@ -1692,7 +1704,7 @@
           reportEndpointAsIs: true,
         });
       });
-    },
+    }
 
     /**
      * @param {string} project
@@ -1722,7 +1734,7 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1750,7 +1762,7 @@
           return {content, type, ok: true};
         });
       });
-    },
+    }
 
     /**
      * Gets a file in a specific change and revision.
@@ -1769,7 +1781,7 @@
         headers: {Accept: 'application/json'},
         anonymizedEndpoint: '/files/*/content',
       });
-    },
+    }
 
     /**
      * Gets a file in a change edit.
@@ -1784,7 +1796,7 @@
         headers: {Accept: 'application/json'},
         anonymizedEndpoint: '/edit/*',
       });
-    },
+    }
 
     rebaseChangeEdit(changeNum) {
       return this._getChangeURLAndSend({
@@ -1793,7 +1805,7 @@
         endpoint: '/edit:rebase',
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     deleteChangeEdit(changeNum) {
       return this._getChangeURLAndSend({
@@ -1802,7 +1814,7 @@
         endpoint: '/edit',
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     restoreFileInChangeEdit(changeNum, restore_path) {
       return this._getChangeURLAndSend({
@@ -1812,7 +1824,7 @@
         body: {restore_path},
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     renameFileInChangeEdit(changeNum, old_path, new_path) {
       return this._getChangeURLAndSend({
@@ -1822,7 +1834,7 @@
         body: {old_path, new_path},
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     deleteFileInChangeEdit(changeNum, path) {
       return this._getChangeURLAndSend({
@@ -1831,7 +1843,7 @@
         endpoint: '/edit/' + encodeURIComponent(path),
         anonymizedEndpoint: '/edit/*',
       });
-    },
+    }
 
     saveChangeEdit(changeNum, path, contents) {
       return this._getChangeURLAndSend({
@@ -1842,7 +1854,7 @@
         contentType: 'text/plain',
         anonymizedEndpoint: '/edit/*',
       });
-    },
+    }
 
     // Deprecated, prefer to use putChangeCommitMessage instead.
     saveChangeCommitMessageEdit(changeNum, message) {
@@ -1853,7 +1865,7 @@
         body: {message},
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     publishChangeEdit(changeNum) {
       return this._getChangeURLAndSend({
@@ -1862,7 +1874,7 @@
         endpoint: '/edit:publish',
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     putChangeCommitMessage(changeNum, message) {
       return this._getChangeURLAndSend({
@@ -1872,7 +1884,7 @@
         body: {message},
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     saveChangeStarred(changeNum, starred) {
       // Some servers may require the project name to be provided
@@ -1887,7 +1899,7 @@
           anonymizedUrl: '/accounts/self/starred.changes/*',
         });
       });
-    },
+    }
 
     saveChangeReviewed(changeNum, reviewed) {
       return this._getChangeURLAndSend({
@@ -1895,7 +1907,7 @@
         method: 'PUT',
         endpoint: reviewed ? '/reviewed' : '/unreviewed',
       });
-    },
+    }
 
     /**
      * Public version of the _restApiHelper.send method preserved for plugins.
@@ -1919,7 +1931,7 @@
         contentType: opt_contentType,
         headers: opt_headers,
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1944,16 +1956,24 @@
         params.base = basePatchNum;
       }
       const endpoint = `/files/${encodeURIComponent(path)}/diff`;
-
-      return this._getChangeURLAndFetch({
+      const req = {
         changeNum,
         endpoint,
         patchNum,
         errFn: opt_errFn,
         params,
         anonymizedEndpoint: '/files/*/diff',
-      });
-    },
+      };
+
+      // Invalidate the cache if its edit patch to make sure we always get latest.
+      if (patchNum === this.EDIT_NAME) {
+        if (!req.fetchOptions) req.fetchOptions = {};
+        if (!req.fetchOptions.headers) req.fetchOptions.headers = new Headers();
+        req.fetchOptions.headers.append('Cache-Control', 'no-cache');
+      }
+
+      return this._getChangeURLAndFetch(req);
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1965,7 +1985,7 @@
     getDiffComments(changeNum, opt_basePatchNum, opt_patchNum, opt_path) {
       return this._getDiffComments(changeNum, '/comments', opt_basePatchNum,
           opt_patchNum, opt_path);
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -1977,7 +1997,7 @@
     getDiffRobotComments(changeNum, opt_basePatchNum, opt_patchNum, opt_path) {
       return this._getDiffComments(changeNum, '/robotcomments',
           opt_basePatchNum, opt_patchNum, opt_path);
-    },
+    }
 
     /**
      * If the user is logged in, fetch the user's draft diff comments. If there
@@ -1996,7 +2016,7 @@
         return this._getDiffComments(changeNum, '/drafts', opt_basePatchNum,
             opt_patchNum, opt_path);
       });
-    },
+    }
 
     _setRange(comments, comment) {
       if (comment.in_reply_to && !comment.range) {
@@ -2008,7 +2028,7 @@
         }
       }
       return comment;
-    },
+    }
 
     _setRanges(comments) {
       comments = comments || [];
@@ -2019,7 +2039,7 @@
         this._setRange(comments, comment);
       }
       return comments;
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -2092,7 +2112,7 @@
           comments,
         });
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -2102,15 +2122,15 @@
     _getDiffCommentsFetchURL(changeNum, endpoint, opt_patchNum) {
       return this._changeBaseURL(changeNum, opt_patchNum)
           .then(url => url + endpoint);
-    },
+    }
 
     saveDiffDraft(changeNum, patchNum, draft) {
       return this._sendDiffDraftRequest('PUT', changeNum, patchNum, draft);
-    },
+    }
 
     deleteDiffDraft(changeNum, patchNum, draft) {
       return this._sendDiffDraftRequest('DELETE', changeNum, patchNum, draft);
-    },
+    }
 
     /**
      * @returns {boolean} Whether there are pending diff draft sends.
@@ -2118,7 +2138,7 @@
     hasPendingDiffDrafts() {
       const promises = this._pendingRequests[Requests.SEND_DIFF_DRAFT];
       return promises && promises.length;
-    },
+    }
 
     /**
      * @returns {!Promise<undefined>} A promise that resolves when all pending
@@ -2129,7 +2149,7 @@
           .then(() => {
             this._pendingRequests[Requests.SEND_DIFF_DRAFT] = [];
           });
-    },
+    }
 
     _sendDiffDraftRequest(method, changeNum, patchNum, draft) {
       const isCreate = !draft.id && method === 'PUT';
@@ -2165,7 +2185,7 @@
       }
 
       return promise;
-    },
+    }
 
     getCommitInfo(project, commit) {
       return this._restApiHelper.fetchJSON({
@@ -2173,7 +2193,7 @@
             '/commits/' + encodeURIComponent(commit),
         anonymizedUrl: '/projects/*/comments/*',
       });
-    },
+    }
 
     _fetchB64File(url) {
       return this._restApiHelper.fetch({url: this.getBaseUrl() + url})
@@ -2187,7 +2207,7 @@
                   return {body: text, type};
                 });
           });
-    },
+    }
 
     /**
      * @param {string} changeId
@@ -2202,7 +2222,7 @@
         url = `${url}/files/${encodeURIComponent(path)}/content${parent}`;
         return this._fetchB64File(url);
       });
-    },
+    }
 
     getImagesForDiff(changeNum, diff, patchRange) {
       let promiseA;
@@ -2244,7 +2264,7 @@
 
         return {baseImage, revisionImage};
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -2265,7 +2285,7 @@
         }
         return url;
       });
-    },
+    }
 
     /**
      * @suppress {checkTypes}
@@ -2281,7 +2301,7 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @suppress {checkTypes}
@@ -2297,7 +2317,7 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     deleteAccountHttpPassword() {
       return this._restApiHelper.send({
@@ -2305,7 +2325,7 @@
         url: '/accounts/self/password.http',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @suppress {checkTypes}
@@ -2320,14 +2340,14 @@
         parseResponse: true,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getAccountSSHKeys() {
       return this._fetchSharedCacheURL({
         url: '/accounts/self/sshkeys',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     addAccountSSHKey(key) {
       const req = {
@@ -2348,7 +2368,7 @@
             if (!obj.valid) { return Promise.reject(new Error('error')); }
             return obj;
           });
-    },
+    }
 
     deleteAccountSSHKey(id) {
       return this._restApiHelper.send({
@@ -2356,14 +2376,14 @@
         url: '/accounts/self/sshkeys/' + id,
         anonymizedUrl: '/accounts/self/sshkeys/*',
       });
-    },
+    }
 
     getAccountGPGKeys() {
       return this._restApiHelper.fetchJSON({
         url: '/accounts/self/gpgkeys',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     addAccountGPGKey(key) {
       const req = {
@@ -2383,7 +2403,7 @@
             if (!obj) { return Promise.reject(new Error('error')); }
             return obj;
           });
-    },
+    }
 
     deleteAccountGPGKey(id) {
       return this._restApiHelper.send({
@@ -2391,7 +2411,7 @@
         url: '/accounts/self/gpgkeys/' + id,
         anonymizedUrl: '/accounts/self/gpgkeys/*',
       });
-    },
+    }
 
     deleteVote(changeNum, account, label) {
       return this._getChangeURLAndSend({
@@ -2400,7 +2420,7 @@
         endpoint: `/reviewers/${account}/votes/${encodeURIComponent(label)}`,
         anonymizedEndpoint: '/reviewers/*/votes/*',
       });
-    },
+    }
 
     setDescription(changeNum, patchNum, desc) {
       return this._getChangeURLAndSend({
@@ -2410,7 +2430,7 @@
         body: {description: desc},
         reportUrlAsIs: true,
       });
-    },
+    }
 
     confirmEmail(token) {
       const req = {
@@ -2425,7 +2445,7 @@
         }
         return null;
       });
-    },
+    }
 
     getCapabilities(opt_errFn) {
       return this._restApiHelper.fetchJSON({
@@ -2433,7 +2453,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     getTopMenus(opt_errFn) {
       return this._fetchSharedCacheURL({
@@ -2441,7 +2461,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     setAssignee(changeNum, assignee) {
       return this._getChangeURLAndSend({
@@ -2451,7 +2471,7 @@
         body: {assignee},
         reportUrlAsIs: true,
       });
-    },
+    }
 
     deleteAssignee(changeNum) {
       return this._getChangeURLAndSend({
@@ -2460,14 +2480,14 @@
         endpoint: '/assignee',
         reportUrlAsIs: true,
       });
-    },
+    }
 
     probePath(path) {
       return fetch(new Request(path, {method: 'HEAD'}))
           .then(response => {
             return response.ok;
           });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -2490,7 +2510,7 @@
           return 'Change marked as Work In Progress.';
         }
       });
-    },
+    }
 
     /**
      * @param {number|string} changeNum
@@ -2506,7 +2526,7 @@
         errFn: opt_errFn,
         reportUrlAsIs: true,
       });
-    },
+    }
 
     /**
      * @suppress {checkTypes}
@@ -2523,7 +2543,7 @@
         parseResponse: true,
         anonymizedEndpoint: '/comments/*/delete',
       });
-    },
+    }
 
     /**
      * Given a changeNum, gets the change.
@@ -2542,7 +2562,7 @@
         if (!res || !res.length) { return null; }
         return res[0];
       });
-    },
+    }
 
     /**
      * @param {string|number} changeNum
@@ -2555,7 +2575,7 @@
             'One of them must be invalid.');
       }
       this._projectLookup[changeNum] = project;
-    },
+    }
 
     /**
      * Checks in _projectLookup for the changeNum. If it exists, returns the
@@ -2579,7 +2599,7 @@
         this.setInProjectLookup(changeNum, change.project);
         return change.project;
       });
-    },
+    }
 
     /**
      * Alias for _changeBaseURL.then(send).
@@ -2606,7 +2626,7 @@
             (anonymizedBaseUrl + anonymizedEndpoint) : undefined,
         });
       });
-    },
+    }
 
     /**
      * Alias for _changeBaseURL.then(_fetchJSON).
@@ -2628,7 +2648,7 @@
             (anonymizedBaseUrl + anonymizedEndpoint) : undefined,
         });
       });
-    },
+    }
 
     /**
      * Execute a change action or revision action on a change.
@@ -2650,7 +2670,7 @@
         body: opt_payload,
         errFn: opt_errFn,
       });
-    },
+    }
 
     /**
      * Get blame information for the given diff.
@@ -2670,7 +2690,7 @@
         params: opt_base ? {base: 't'} : undefined,
         anonymizedEndpoint: '/files/*/blame',
       });
-    },
+    }
 
     /**
      * Modify the given create draft request promise so that it fails and throws
@@ -2699,7 +2719,7 @@
         }
         return result;
       });
-    },
+    }
 
     /**
      * Fetch a project dashboard definition.
@@ -2718,7 +2738,7 @@
         errFn: opt_errFn,
         anonymizedUrl: '/projects/*/dashboards/*',
       });
-    },
+    }
 
     /**
      * @param {string} filter
@@ -2734,7 +2754,7 @@
         url: `/Documentation/?q=${encodedFilter}`,
         anonymizedUrl: '/Documentation/?*',
       });
-    },
+    }
 
     getMergeable(changeNum) {
       return this._getChangeURLAndFetch({
@@ -2743,7 +2763,7 @@
         parseResponse: true,
         reportEndpointAsIs: true,
       });
-    },
+    }
 
     deleteDraftComments(query) {
       return this._restApiHelper.send({
@@ -2751,6 +2771,8 @@
         url: '/accounts/self/drafts:delete',
         body: {query},
       });
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRestApiInterface.is, GrRestApiInterface);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index 9f01f48..a598d0d 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-rest-api-interface</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html
index 4eaf1bc..446cfc8 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-rest-api-helper</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
index fdf79af..ad3e4ca 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reviewer-updates-parser</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-select/gr-select.js b/polygerrit-ui/app/elements/shared/gr-select/gr-select.js
index 05267ba..152834f 100644
--- a/polygerrit-ui/app/elements/shared/gr-select/gr-select.js
+++ b/polygerrit-ui/app/elements/shared/gr-select/gr-select.js
@@ -17,29 +17,29 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-select',
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    */
+  class GrSelect extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-select'; }
 
-    properties: {
-      bindValue: {
-        type: String,
-        notify: true,
-        observer: '_updateValue',
-      },
-    },
-
-    behaviors: [
-      Gerrit.FireBehavior,
-    ],
-
-    listeners: {
-      'change': '_valueChanged',
-      'dom-change': '_updateValue',
-    },
+    static get properties() {
+      return {
+        bindValue: {
+          type: String,
+          notify: true,
+          observer: '_updateValue',
+        },
+      };
+    }
 
     get nativeSelect() {
       return this.$$('select');
-    },
+    }
 
     _updateValue() {
       // It's possible to have a value of 0.
@@ -53,21 +53,32 @@
           this.nativeSelect.value = this.bindValue;
         }, 1);
       }
-    },
+    }
 
     _valueChanged() {
       this.bindValue = this.nativeSelect.value;
-    },
+    }
 
     focus() {
       this.nativeSelect.focus();
-    },
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('change',
+          () => this._valueChanged());
+      this.addEventListener('dom-change',
+          () => this._updateValue());
+    }
 
     ready() {
+      super.ready();
       // If not set via the property, set bind-value to the element value.
       if (this.bindValue == undefined && this.nativeSelect.options.length > 0) {
         this.bindValue = this.nativeSelect.value;
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrSelect.is, GrSelect);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html b/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html
index b3abe5f..cae61056 100644
--- a/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-select/gr-select_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-select</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command.js b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command.js
index 2c546cc..9456991 100644
--- a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command.js
+++ b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command.js
@@ -17,16 +17,22 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-shell-command',
+  class GrShellCommand extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-shell-command'; }
 
-    properties: {
-      command: String,
-      label: String,
-    },
+    static get properties() {
+      return {
+        command: String,
+        label: String,
+      };
+    }
 
     focusOnCopy() {
       this.$$('gr-copy-clipboard').focusOnCopy();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrShellCommand.is, GrShellCommand);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html
index 3f2f8ba..a4bdf58 100644
--- a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-shell-command</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
index f6ade6e..7950e51 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
@@ -28,52 +28,56 @@
     'editablecontent:',
   ];
 
-  Polymer({
-    is: 'gr-storage',
+  class GrStorage extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-storage'; }
 
-    properties: {
-      _lastCleanup: Number,
-      /** @type {?Storage} */
-      _storage: {
-        type: Object,
-        value() {
-          return window.localStorage;
+    static get properties() {
+      return {
+        _lastCleanup: Number,
+        /** @type {?Storage} */
+        _storage: {
+          type: Object,
+          value() {
+            return window.localStorage;
+          },
         },
-      },
-      _exceededQuota: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _exceededQuota: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
     getDraftComment(location) {
       this._cleanupItems();
       return this._getObject(this._getDraftKey(location));
-    },
+    }
 
     setDraftComment(location, message) {
       const key = this._getDraftKey(location);
       this._setObject(key, {message, updated: Date.now()});
-    },
+    }
 
     eraseDraftComment(location) {
       const key = this._getDraftKey(location);
       this._storage.removeItem(key);
-    },
+    }
 
     getEditableContentItem(key) {
       this._cleanupItems();
       return this._getObject(this._getEditableContentKey(key));
-    },
+    }
 
     setEditableContentItem(key, message) {
       this._setObject(this._getEditableContentKey(key),
           {message, updated: Date.now()});
-    },
+    }
 
     eraseEditableContentItem(key) {
       this._storage.removeItem(this._getEditableContentKey(key));
-    },
+    }
 
     _getDraftKey(location) {
       const range = location.range ?
@@ -86,11 +90,11 @@
         key = key + ':' + range;
       }
       return key;
-    },
+    }
 
     _getEditableContentKey(key) {
       return `editablecontent:${key}`;
-    },
+    }
 
     _cleanupItems() {
       // Throttle cleanup to the throttle interval.
@@ -113,13 +117,13 @@
           }
         }
       }
-    },
+    }
 
     _getObject(key) {
       const serial = this._storage.getItem(key);
       if (!serial) { return null; }
       return JSON.parse(serial);
-    },
+    }
 
     _setObject(key, obj) {
       if (this._exceededQuota) { return; }
@@ -136,6 +140,8 @@
           throw exc;
         }
       }
-    },
-  });
+    }
+  }
+
+  customElements.define(GrStorage.is, GrStorage);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
index 0482584..5cd4d3e 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-storage</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.js b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.js
index 4c4b038..5011067 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.js
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea.js
@@ -52,73 +52,81 @@
     {value: '😜', match: 'winking tongue ;)'},
   ];
 
-  Polymer({
-    is: 'gr-textarea',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    */
+  class GrTextarea extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-textarea'; }
     /**
      * @event bind-value-changed
      */
 
-    properties: {
-      autocomplete: Boolean,
-      disabled: Boolean,
-      rows: Number,
-      maxRows: Number,
-      placeholder: String,
-      text: {
-        type: String,
-        notify: true,
-        observer: '_handleTextChanged',
-      },
-      hideBorder: {
-        type: Boolean,
-        value: false,
-      },
-      /** Text input should be rendered in monspace font.  */
-      monospace: {
-        type: Boolean,
-        value: false,
-      },
-      /** Text input should be rendered in code font, which is smaller than the
+    static get properties() {
+      return {
+        autocomplete: Boolean,
+        disabled: Boolean,
+        rows: Number,
+        maxRows: Number,
+        placeholder: String,
+        text: {
+          type: String,
+          notify: true,
+          observer: '_handleTextChanged',
+        },
+        hideBorder: {
+          type: Boolean,
+          value: false,
+        },
+        /** Text input should be rendered in monspace font.  */
+        monospace: {
+          type: Boolean,
+          value: false,
+        },
+        /** Text input should be rendered in code font, which is smaller than the
           standard monospace font. */
-      code: {
-        type: Boolean,
-        value: false,
-      },
-      /** @type(?number) */
-      _colonIndex: Number,
-      _currentSearchString: {
-        type: String,
-        observer: '_determineSuggestions',
-      },
-      _hideAutocomplete: {
-        type: Boolean,
-        value: true,
-      },
-      _index: Number,
-      _suggestions: Array,
-      // Offset makes dropdown appear below text.
-      _verticalOffset: {
-        type: Number,
-        value: 20,
-        readOnly: true,
-      },
-    },
+        code: {
+          type: Boolean,
+          value: false,
+        },
+        /** @type(?number) */
+        _colonIndex: Number,
+        _currentSearchString: {
+          type: String,
+          observer: '_determineSuggestions',
+        },
+        _hideAutocomplete: {
+          type: Boolean,
+          value: true,
+        },
+        _index: Number,
+        _suggestions: Array,
+        // Offset makes dropdown appear below text.
+        _verticalOffset: {
+          type: Number,
+          value: 20,
+          readOnly: true,
+        },
+      };
+    }
 
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-    ],
-
-    keyBindings: {
-      esc: '_handleEscKey',
-      tab: '_handleEnterByKey',
-      enter: '_handleEnterByKey',
-      up: '_handleUpKey',
-      down: '_handleDownKey',
-    },
+    get keyBindings() {
+      return {
+        esc: '_handleEscKey',
+        tab: '_handleEnterByKey',
+        enter: '_handleEnterByKey',
+        up: '_handleUpKey',
+        down: '_handleDownKey',
+      };
+    }
 
     ready() {
+      super.ready();
       if (this.monospace) {
         this.classList.add('monospace');
       }
@@ -128,15 +136,15 @@
       if (this.hideBorder) {
         this.$.textarea.classList.add('noBorder');
       }
-    },
+    }
 
     closeDropdown() {
       return this.$.emojiSuggestions.close();
-    },
+    }
 
     getNativeTextarea() {
       return this.$.textarea.textarea;
-    },
+    }
 
     putCursorAtEnd() {
       const textarea = this.getNativeTextarea();
@@ -146,14 +154,14 @@
       this.async(() => {
         textarea.focus();
       });
-    },
+    }
 
     _handleEscKey(e) {
       if (this._hideAutocomplete) { return; }
       e.preventDefault();
       e.stopPropagation();
       this._resetEmojiDropdown();
-    },
+    }
 
     _handleUpKey(e) {
       if (this._hideAutocomplete) { return; }
@@ -162,7 +170,7 @@
       this.$.emojiSuggestions.cursorUp();
       this.$.textarea.textarea.focus();
       this.disableEnterKeyForSelectingEmoji = false;
-    },
+    }
 
     _handleDownKey(e) {
       if (this._hideAutocomplete) { return; }
@@ -171,7 +179,7 @@
       this.$.emojiSuggestions.cursorDown();
       this.$.textarea.textarea.focus();
       this.disableEnterKeyForSelectingEmoji = false;
-    },
+    }
 
     _handleEnterByKey(e) {
       if (this._hideAutocomplete || this.disableEnterKeyForSelectingEmoji) {
@@ -180,11 +188,11 @@
       e.preventDefault();
       e.stopPropagation();
       this._setEmoji(this.$.emojiSuggestions.getCurrentText());
-    },
+    }
 
     _handleEmojiSelect(e) {
       this._setEmoji(e.detail.selected.dataset.value);
-    },
+    }
 
     _setEmoji(text) {
       const colonIndex = this._colonIndex;
@@ -193,12 +201,13 @@
       this.$.textarea.selectionEnd = colonIndex + 1;
       this.$.reporting.reportInteraction('select-emoji');
       this._resetEmojiDropdown();
-    },
+    }
 
     _getText(value) {
       return this.text.substr(0, this._colonIndex || 0) +
           value + this.text.substr(this.$.textarea.selectionStart);
-    },
+    }
+
     /**
      * Uses a hidden element with the same width and styling of the textarea and
      * the text up until the point of interest. Then caratSpan element is added
@@ -214,17 +223,17 @@
       this.$.hiddenText.appendChild(caratSpan);
       this.$.emojiSuggestions.positionTarget = caratSpan;
       this._openEmojiDropdown();
-    },
+    }
 
     _getFontSize() {
       const fontSizePx = getComputedStyle(this).fontSize || '12px';
       return parseInt(fontSizePx.substr(0, fontSizePx.length - 2),
           10);
-    },
+    }
 
     _getScrollTop() {
       return document.body.scrollTop;
-    },
+    }
 
     /**
      * _handleKeydown used for key handling in the this.$.textarea AND all child
@@ -271,12 +280,12 @@
         this._updateCaratPosition();
       }
       this.$.textarea.textarea.focus();
-    },
+    }
 
     _openEmojiDropdown() {
       this.$.emojiSuggestions.open();
       this.$.reporting.reportInteraction('open-emoji-dropdown');
-    },
+    }
 
     _formatSuggestions(matchedSuggestions) {
       const suggestions = [];
@@ -286,7 +295,7 @@
         suggestions.push(suggestion);
       }
       this.set('_suggestions', suggestions);
-    },
+    }
 
     _determineSuggestions(emojiText) {
       if (!emojiText.length) {
@@ -299,7 +308,7 @@
         this._formatSuggestions(matches);
         this.disableEnterKeyForSelectingEmoji = false;
       }
-    },
+    }
 
     _resetEmojiDropdown() {
       // hide and reset the autocomplete dropdown.
@@ -309,11 +318,13 @@
       this.closeDropdown();
       this._colonIndex = null;
       this.$.textarea.textarea.focus();
-    },
+    }
 
     _handleTextChanged(text) {
       this.dispatchEvent(
           new CustomEvent('value-changed', {detail: {value: text}}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrTextarea.is, GrTextarea);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html
index b884ecd..699deab 100644
--- a/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-textarea/gr-textarea_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-textarea</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content.js b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content.js
index c5de8f4..3559949 100644
--- a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content.js
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content.js
@@ -17,31 +17,38 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-tooltip-content',
+  /**
+    * @appliesMixin Gerrit.TooltipMixin
+    */
+  class GrTooltipContent extends Polymer.mixinBehaviors( [
+    Gerrit.TooltipBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-tooltip-content'; }
 
-    properties: {
-      title: {
-        type: String,
-        reflectToAttribute: true,
-      },
-      maxWidth: {
-        type: String,
-        reflectToAttribute: true,
-      },
-      positionBelow: {
-        type: Boolean,
-        valye: false,
-        reflectToAttribute: true,
-      },
-      showIcon: {
-        type: Boolean,
-        value: false,
-      },
-    },
+    static get properties() {
+      return {
+        title: {
+          type: String,
+          reflectToAttribute: true,
+        },
+        maxWidth: {
+          type: String,
+          reflectToAttribute: true,
+        },
+        positionBelow: {
+          type: Boolean,
+          valye: false,
+          reflectToAttribute: true,
+        },
+        showIcon: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
+  }
 
-    behaviors: [
-      Gerrit.TooltipBehavior,
-    ],
-  });
+  customElements.define(GrTooltipContent.is, GrTooltipContent);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html
index f9350c6..4276195 100644
--- a/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip-content/gr-tooltip-content_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-storage</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js
index fb87b558..170a442 100644
--- a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip.js
@@ -17,23 +17,29 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-tooltip',
+  class GrTooltip extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-tooltip'; }
 
-    properties: {
-      text: String,
-      maxWidth: {
-        type: String,
-        observer: '_updateWidth',
-      },
-      positionBelow: {
-        type: Boolean,
-        reflectToAttribute: true,
-      },
-    },
+    static get properties() {
+      return {
+        text: String,
+        maxWidth: {
+          type: String,
+          observer: '_updateWidth',
+        },
+        positionBelow: {
+          type: Boolean,
+          reflectToAttribute: true,
+        },
+      };
+    }
 
     _updateWidth(maxWidth) {
       this.updateStyles({'--tooltip-max-width': maxWidth});
-    },
-  });
+    }
+  }
+
+  customElements.define(GrTooltip.is, GrTooltip);
 })();
diff --git a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html
index f59f6e1..95f3922 100644
--- a/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-tooltip/gr-tooltip_test.html
@@ -17,7 +17,7 @@
 -->
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-storage</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html b/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html
index 7e5810b..187ce35 100644
--- a/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html
+++ b/polygerrit-ui/app/elements/shared/revision-info/revision-info_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>revision-info</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/embed/embed_test.html b/polygerrit-ui/app/embed/embed_test.html
index 048dffa..5d81b7e 100644
--- a/polygerrit-ui/app/embed/embed_test.html
+++ b/polygerrit-ui/app/embed/embed_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>embed_test</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/polylint_test.sh b/polygerrit-ui/app/polylint_test.sh
index f6880a1..98cf06f 100755
--- a/polygerrit-ui/app/polylint_test.sh
+++ b/polygerrit-ui/app/polylint_test.sh
@@ -8,13 +8,24 @@
     exit 1
 fi
 
-npx_bin=$(which npx)
-if [[ -z "$npx_bin" ]]; then
-    echo "NPX must be on the path."
-    echo "> npm i -g npx"
+node_bin=$(which node)
+if [[ -z "$node_bin" ]]; then
+    echo "node must be on the path."
+    exit 1
+fi
+
+polymer_bin=$(which polymer)
+if [[ -z "$polymer_bin" ]]; then
+  polymer_bin=$(abs_path ./node_modules/polymer-cli/bin/polymer.js);
+fi
+if [[ -z "$polymer_bin" ]]; then
+    echo "polymer must be set or polymer-cli locally installed (npm install polymer-cli)."
     exit 1
 fi
 
 unzip -o polygerrit-ui/polygerrit_components.bower_components.zip -d polygerrit-ui/app
 
-npx polylint --root polygerrit-ui/app --input elements/gr-app.html --b 'bower_components' --verbose
+#Can't use --root with polymer.json - see https://github.com/Polymer/tools/issues/2616
+#Change current directory to the root folder
+cd polygerrit-ui/app
+$polymer_bin lint --component-dir 'bower_components' --verbose
diff --git a/polygerrit-ui/app/polymer.json b/polygerrit-ui/app/polymer.json
new file mode 100644
index 0000000..411c969
--- /dev/null
+++ b/polygerrit-ui/app/polymer.json
@@ -0,0 +1,14 @@
+{
+  "entrypoint": "elements/gr-app.html",
+  "sources": [
+    "behaviors/**/*",
+    "elements/**/*",
+    "scripts/**/*",
+    "styles/*",
+    "types/**/*"
+  ],
+  "lint": {
+    "rules": ["polymer-2"],
+    "ignoreWarnings": ["deprecated-dom-call"]
+  }
+}
diff --git a/polygerrit-ui/app/samples/coverage-plugin.html b/polygerrit-ui/app/samples/coverage-plugin.html
index e4c23aa..fa44a47 100644
--- a/polygerrit-ui/app/samples/coverage-plugin.html
+++ b/polygerrit-ui/app/samples/coverage-plugin.html
@@ -60,6 +60,8 @@
       }).enableToggleCheckbox('Display Coverage', checkbox => {
         // Checkbox is attached so now add the notifier that will be controlled
         // by the checkbox.
+        // Checkbox will only be added to the file diff page, in the top right
+        // section near the "Diff view".
         annotationApi.addNotifier(notifyFunc => {
           new Promise(resolve => setTimeout(resolve, 3000)).then(() => {
             populateWithDummyData(coverageData);
diff --git a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
index b04e324..a35e034 100644
--- a/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
+++ b/polygerrit-ui/app/scripts/gr-display-name-utils/gr-display-name-utils_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-display-name-utils</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html
index 0266ab9..ac32efa 100644
--- a/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html
+++ b/polygerrit-ui/app/scripts/gr-email-suggestions-provider/gr-email-suggestions-provider_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-email-suggestions-provider</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html
index b60aaa9..6908256 100644
--- a/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html
+++ b/polygerrit-ui/app/scripts/gr-group-suggestions-provider/gr-group-suggestions-provider_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-group-suggestions-provider</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html
index ca3c277..6fcc4dc 100644
--- a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html
+++ b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider_test.html
@@ -18,7 +18,7 @@
 
 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
 <title>gr-reviewer-suggestions-provider</title>
-<script src="/test/common-test-setup.js"></script>
+
 <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>
 
 <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
diff --git a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
index fef3872..84692ba 100644
--- a/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-metadata-shared-styles.html
@@ -16,7 +16,9 @@
 -->
 <dom-module id="gr-change-metadata-shared-styles">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style>
       section {
         display: table-row;
diff --git a/polygerrit-ui/app/styles/gr-change-view-integration-shared-styles.html b/polygerrit-ui/app/styles/gr-change-view-integration-shared-styles.html
index 834f64a..5c5194c 100644
--- a/polygerrit-ui/app/styles/gr-change-view-integration-shared-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-view-integration-shared-styles.html
@@ -25,7 +25,9 @@
 -->
 <dom-module id="gr-change-view-integration-shared-styles">
   <template>
-    <style include="shared-styles"></style>
+    <style include="shared-styles">
+      /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
+    </style>
     <style>
       .header {
         color: var(--primary-text-color);
diff --git a/polygerrit-ui/app/styles/gr-form-styles.html b/polygerrit-ui/app/styles/gr-form-styles.html
index 3fe0a72..7c9ae0d 100644
--- a/polygerrit-ui/app/styles/gr-form-styles.html
+++ b/polygerrit-ui/app/styles/gr-form-styles.html
@@ -61,7 +61,6 @@
       }
       .gr-form-styles td,
       .gr-form-styles tfoot th {
-        height: 2em;
         padding: var(--spacing-s) 0;
         vertical-align: middle;
       }
@@ -84,8 +83,7 @@
       .gr-form-styles textarea {
         border: 1px solid var(--border-color);
         border-radius: var(--border-radius);
-        height: 2em;
-        padding: 0 var(--spacing-xs);
+        padding: var(--spacing-s);
       }
       .gr-form-styles td:last-child {
         width: 5em;
@@ -97,23 +95,16 @@
       .gr-form-styles iron-autogrow-textarea {
         border: none;
         height: auto;
-        min-height: 2em;
+        min-height: 4em;
         --iron-autogrow-textarea: {
           border: 1px solid var(--border-color);
           border-radius: var(--border-radius);
           box-sizing: border-box;
-          padding: var(--spacing-s) var(--spacing-xs) 0 var(--spacing-xs);
+          padding: var(--spacing-s);
         }
       }
       .gr-form-styles gr-autocomplete {
-        border: none;
-        --gr-autocomplete: {
-          border: 1px solid var(--border-color);
-          border-radius: var(--border-radius);
-          height: 2em;
-          padding: 0 var(--spacing-xs);
-          width: 14em;
-        }
+        width: 14em;
       }
       @media only screen and (max-width: 40em) {
         .gr-form-styles section {
diff --git a/polygerrit-ui/app/styles/shared-styles.html b/polygerrit-ui/app/styles/shared-styles.html
index 5314741..51b92e1 100644
--- a/polygerrit-ui/app/styles/shared-styles.html
+++ b/polygerrit-ui/app/styles/shared-styles.html
@@ -42,10 +42,11 @@
       input {
         background-color: inherit;
         border: 1px solid var(--border-color);
+        border-radius: var(--border-radius);
         box-sizing: border-box;
         color: var(--primary-text-color);
         margin: 0;
-        padding: 0;
+        padding: var(--spacing-s);
       }
       iron-autogrow-textarea {
         background-color: inherit;
diff --git a/polygerrit-ui/app/styles/themes/app-theme.html b/polygerrit-ui/app/styles/themes/app-theme.html
index 948aa1a..ccdde2b 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.html
+++ b/polygerrit-ui/app/styles/themes/app-theme.html
@@ -107,6 +107,7 @@
   --header-background-color: #eee;
   --header-border-bottom: 1px solid var(--border-color);
   --header-border-image: '';
+  --header-box-shadow: none;
   --header-padding: 0 var(--spacing-l);
   --header-icon-size: 0em;
   --header-icon: none;
@@ -132,6 +133,8 @@
   --light-rebased-add-highlight-color: #eef;
   --light-remove-add-highlight-color: #fff8dc;
   --light-remove-highlight-color: #ffebee;
+  --coverage-covered: #e0f2f1;
+  --coverage-not-covered: #ffd1a4;
 
   /* syntax colors */
   --syntax-attr-color: #219;
diff --git a/polygerrit-ui/app/styles/themes/dark-theme.html b/polygerrit-ui/app/styles/themes/dark-theme.html
index cd5f9dd..f3d5e78 100644
--- a/polygerrit-ui/app/styles/themes/dark-theme.html
+++ b/polygerrit-ui/app/styles/themes/dark-theme.html
@@ -103,6 +103,8 @@
       --light-rebased-add-highlight-color: #487165;
       --light-remove-add-highlight-color: #2f3f2f;
       --light-remove-highlight-color: #320404;
+      --coverage-covered: #e0f2f1;
+      --coverage-not-covered: #ffd1a4;
 
       /* syntax colors */
       --syntax-attr-color: #80cbbf;
diff --git a/polygerrit-ui/app/template_test.sh b/polygerrit-ui/app/template_test.sh
index b1a2380..ccefd83 100755
--- a/polygerrit-ui/app/template_test.sh
+++ b/polygerrit-ui/app/template_test.sh
@@ -1,5 +1,11 @@
 #!/bin/bash
 
+# TODO(dmfilippov): Update template_test to support Polymer 2/Polymer 3 or delete it completely
+# The following line temporary disable template tests. Existing implementation doesn't compatible
+# with Polymer 2 & 3 class-based components. Polymer linter makes some checks regarding
+# templates and binding, but not all.
+exit 0
+
 set -ex
 
 node_bin=$(which node)
diff --git a/polygerrit-ui/app/test/common-test-setup.js b/polygerrit-ui/app/test/common-test-setup.js
deleted file mode 100644
index 7ceff7e..0000000
--- a/polygerrit-ui/app/test/common-test-setup.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * @license
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Helps looking up the proper iron-input element during the Polymer 2
- * transition. Polymer 2 uses the <iron-input> element, while Polymer 1 uses
- * the nested <input is="iron-input"> element.
- */
-window.ironInput = function(element) {
-  return Polymer.dom(element).querySelector(
-      Polymer.Element ? 'iron-input' : 'input[is=iron-input]');
-};
diff --git a/polygerrit-ui/app/types/polymer-behaviors.js b/polygerrit-ui/app/types/polymer-behaviors.js
new file mode 100644
index 0000000..18e7ad9
--- /dev/null
+++ b/polygerrit-ui/app/types/polymer-behaviors.js
@@ -0,0 +1,52 @@
+/**
+ * @license
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * For the purposes of template type checking, externs should be added for
+ * anything set on the window object. Note that sub-properties of these
+ * declared properties are considered something separate.
+ *
+ * This file is only for template type checking, not used in Gerrit code.
+ */
+
+/* eslint-disable no-var */
+/* eslint-disable no-unused-vars */
+
+function PolymerMixins() {
+  // This function must not be called.
+  // Due to an issue in polymer linter the linter can't
+  // process correctly some behaviors from Polymer library.
+  // To workaround this issue, here we define a minimal mixin to allow
+  // linter process our code correctly. You can add more properties to mixins
+  // if needed.
+
+  // Important! Use mixins from these file only inside JSDoc comments.
+  // Do not use it in the real code
+
+  /**
+   * @polymer
+   * @mixinFunction
+   * */
+  Polymer.IronFitMixin = base =>
+    class extends base {
+      static get properties() {
+        return {
+          positionTarget: Object,
+        };
+      }
+    };
+}
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index 35bdefd..3b699c2 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -86,6 +86,9 @@
 		log.Println("Local plugins from", "../plugins")
 	} else {
 		http.HandleFunc("/plugins/", handleProxy)
+		// Serve local plugins from `plugins_`
+		http.Handle("/plugins_/", http.StripPrefix("/plugins_/",
+			http.FileServer(http.Dir("../plugins"))))
 	}
 	log.Println("Serving on port", *port)
 	log.Fatal(http.ListenAndServe(*port, &server{}))
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index 6788bc9..357faa4 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -8,9 +8,196 @@
     enforced by //lib:nongoogle_test.
     """
 
+    maven_jar(
+        name = "j2objc",
+        artifact = "com.google.j2objc:j2objc-annotations:1.1",
+        sha1 = "ed28ded51a8b1c6b112568def5f4b455e6809019",
+    )
+
     # Transitive dependency of commons-compress
     maven_jar(
         name = "tukaani-xz",
         artifact = "org.tukaani:xz:1.8",
         sha1 = "c4f7d054303948eb6a4066194253886c8af07128",
     )
+
+    maven_jar(
+        name = "dropwizard-core",
+        artifact = "io.dropwizard.metrics:metrics-core:4.1.1",
+        sha1 = "ebfafc716d9c3b6151dc7c2c09ce925a163a4f21",
+    )
+
+    SSHD_VERS = "2.3.0"
+
+    maven_jar(
+        name = "sshd",
+        artifact = "org.apache.sshd:sshd-core:" + SSHD_VERS,
+        sha1 = "21aeea9deba96c9b81ea0935fa4fac61aa3cf646",
+    )
+
+    maven_jar(
+        name = "sshd-common",
+        artifact = "org.apache.sshd:sshd-common:" + SSHD_VERS,
+        sha1 = "8b6e3baaa0d35b547696965eef3e62477f5e74c9",
+    )
+
+    maven_jar(
+        name = "eddsa",
+        artifact = "net.i2p.crypto:eddsa:0.3.0",
+        sha1 = "1901c8d4d8bffb7d79027686cfb91e704217c3e1",
+    )
+
+    maven_jar(
+        name = "mina-core",
+        artifact = "org.apache.mina:mina-core:2.0.21",
+        sha1 = "e1a317689ecd438f54e863747e832f741ef8e092",
+    )
+
+    maven_jar(
+        name = "sshd-mina",
+        artifact = "org.apache.sshd:sshd-mina:" + SSHD_VERS,
+        sha1 = "55dc0830dfcbceba01f9460812ee454978a15fe8",
+    )
+
+    # elasticsearch-rest-client explicitly depends on this version
+    maven_jar(
+        name = "httpasyncclient",
+        artifact = "org.apache.httpcomponents:httpasyncclient:4.1.4",
+        sha1 = "f3a3240681faae3fa46b573a4c7e50cec9db0d86",
+    )
+
+    # elasticsearch-rest-client explicitly depends on this version
+    maven_jar(
+        name = "httpcore-nio",
+        artifact = "org.apache.httpcomponents:httpcore-nio:4.4.11",
+        sha1 = "7d0a97d01d39cff9aa3e6db81f21fddb2435f4e6",
+    )
+
+    maven_jar(
+        name = "openid-consumer",
+        artifact = "org.openid4java:openid4java:1.0.0",
+        sha1 = "541091bb49f2c0d583544c5bb1e6df7612d31e3e",
+    )
+
+    maven_jar(
+        name = "nekohtml",
+        artifact = "net.sourceforge.nekohtml:nekohtml:1.9.10",
+        sha1 = "14052461031a7054aa094f5573792feb6686d3de",
+    )
+
+    maven_jar(
+        name = "xerces",
+        artifact = "xerces:xercesImpl:2.8.1",
+        attach_source = False,
+        sha1 = "25101e37ec0c907db6f0612cbf106ee519c1aef1",
+    )
+
+    maven_jar(
+        name = "jruby",
+        artifact = "org.jruby:jruby-complete:9.1.17.0",
+        sha1 = "76716d529710fc03d1d429b43e3cedd4419f78d4",
+    )
+
+    # When upgrading elasticsearch-rest-client, also upgrade httpcore-nio
+    # and httpasyncclient as necessary.
+    maven_jar(
+        name = "elasticsearch-rest-client",
+        artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.4.2",
+        sha1 = "f48725523c0b3402f869214433602f8d3f4c737c",
+    )
+
+    maven_jar(
+        name = "jackson-core",
+        artifact = "com.fasterxml.jackson.core:jackson-core:2.10.1",
+        sha1 = "2c8b5e26ba40e5f91eb37a24075a2028b402c5f9",
+    )
+
+    # Test-only dependencies below.
+
+    maven_jar(
+        name = "cglib-3_2",
+        artifact = "cglib:cglib-nodep:3.2.6",
+        sha1 = "92bf48723d277d6efd1150b2f7e9e1e92cb56caf",
+    )
+
+    maven_jar(
+        name = "objenesis",
+        artifact = "org.objenesis:objenesis:1.3",
+        sha1 = "dc13ae4faca6df981fc7aeb5a522d9db446d5d50",
+    )
+
+    POWERM_VERS = "1.6.1"
+
+    maven_jar(
+        name = "powermock-module-junit4",
+        artifact = "org.powermock:powermock-module-junit4:" + POWERM_VERS,
+        sha1 = "ea8530b2848542624f110a393513af397b37b9cf",
+    )
+
+    maven_jar(
+        name = "powermock-module-junit4-common",
+        artifact = "org.powermock:powermock-module-junit4-common:" + POWERM_VERS,
+        sha1 = "7222ced54dabc310895d02e45c5428ca05193cda",
+    )
+
+    maven_jar(
+        name = "powermock-reflect",
+        artifact = "org.powermock:powermock-reflect:" + POWERM_VERS,
+        sha1 = "97d25eda8275c11161bcddda6ef8beabd534c878",
+    )
+
+    maven_jar(
+        name = "powermock-api-easymock",
+        artifact = "org.powermock:powermock-api-easymock:" + POWERM_VERS,
+        sha1 = "aa740ecf89a2f64d410b3d93ef8cd6833009ef00",
+    )
+
+    maven_jar(
+        name = "powermock-api-support",
+        artifact = "org.powermock:powermock-api-support:" + POWERM_VERS,
+        sha1 = "592ee6d929c324109d3469501222e0c76ccf0869",
+    )
+
+    maven_jar(
+        name = "powermock-core",
+        artifact = "org.powermock:powermock-core:" + POWERM_VERS,
+        sha1 = "5afc1efce8d44ed76b30af939657bd598e45d962",
+    )
+
+    maven_jar(
+        name = "javassist",
+        artifact = "org.javassist:javassist:3.22.0-GA",
+        sha1 = "3e83394258ae2089be7219b971ec21a8288528ad",
+    )
+
+    TESTCONTAINERS_VERSION = "1.12.3"
+
+    maven_jar(
+        name = "testcontainers",
+        artifact = "org.testcontainers:testcontainers:" + TESTCONTAINERS_VERSION,
+        sha1 = "e424a4549640e120acceac641ac909fcda58bf62",
+    )
+
+    maven_jar(
+        name = "testcontainers-elasticsearch",
+        artifact = "org.testcontainers:elasticsearch:" + TESTCONTAINERS_VERSION,
+        sha1 = "c0796de5032070b8768ce78c78949b48f13c30db",
+    )
+
+    maven_jar(
+        name = "duct-tape",
+        artifact = "org.rnorth.duct-tape:duct-tape:1.0.7",
+        sha1 = "a26b5d90d88c91321dc7a3734ea72d2fc019ebb6",
+    )
+
+    maven_jar(
+        name = "visible-assertions",
+        artifact = "org.rnorth.visible-assertions:visible-assertions:2.1.2",
+        sha1 = "20d31a578030ec8e941888537267d3123c2ad1c1",
+    )
+
+    maven_jar(
+        name = "jna",
+        artifact = "net.java.dev.jna:jna:5.2.0",
+        sha1 = "ed8b772eb077a9cb50e44e90899c66a9a6c00e67",
+    )
diff --git a/tools/polygerrit-updater/.gitignore b/tools/polygerrit-updater/.gitignore
new file mode 100644
index 0000000..8619a37
--- /dev/null
+++ b/tools/polygerrit-updater/.gitignore
@@ -0,0 +1,3 @@
+/.idea/
+/node_modules/
+/js/
\ No newline at end of file
diff --git a/tools/polygerrit-updater/package-lock.json b/tools/polygerrit-updater/package-lock.json
new file mode 100644
index 0000000..9256997
--- /dev/null
+++ b/tools/polygerrit-updater/package-lock.json
@@ -0,0 +1,18 @@
+{
+  "name": "polygerrit-updater",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@types/node": {
+      "version": "12.7.12",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz",
+      "integrity": "sha512-KPYGmfD0/b1eXurQ59fXD1GBzhSQfz6/lKBxkaHX9dKTzjXbK68Zt7yGUxUsCS1jeTy/8aL+d9JEr+S54mpkWQ=="
+    },
+    "typescript": {
+      "version": "3.6.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
+      "integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg=="
+    }
+  }
+}
diff --git a/tools/polygerrit-updater/package.json b/tools/polygerrit-updater/package.json
new file mode 100644
index 0000000..3609dad
--- /dev/null
+++ b/tools/polygerrit-updater/package.json
@@ -0,0 +1,15 @@
+{
+  "name": "polygerrit-updater",
+  "version": "1.0.0",
+  "description": "Polygerrit source code updater",
+  "scripts": {
+    "compile": "tsc",
+    "convert": "npm run compile && node js/src/index.js"
+  },
+  "author": "",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "@types/node": "^12.7.12",
+    "typescript": "^3.6.4"
+  }
+}
diff --git a/tools/polygerrit-updater/readme.txt b/tools/polygerrit-updater/readme.txt
new file mode 100644
index 0000000..2b2cea8
--- /dev/null
+++ b/tools/polygerrit-updater/readme.txt
@@ -0,0 +1,56 @@
+This folder contains tool to update Polymer components to class based components.
+This is a temporary tools, it will be removed in a few weeks.
+
+How to use this tool: initial steps
+1) Important - Commit and push all your changes. Otherwise, you can loose you work.
+
+2) Ensure, that tools/polygerrit-updater is your current directory
+
+3) Run
+npm install
+
+4) If you want to convert the whole project, run
+npm run convert -- --i \
+  --root ../../polygerrit-ui --src app/elements --r \
+  --exclude app/elements/core/gr-reporting/gr-reporting.js \
+     app/elements/diff/gr-comment-api/gr-comment-api-mock.js \
+     app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
+
+You can convert only specific files (can be useful if you want to convert some files in your change)
+npm run convert -- --i \
+  --root ../../polygerrit-ui
+  --src app/elements/file1.js \
+      app/elements/folder/file2.js
+
+4) Search for the following string in all .js files:
+//This file has the following problems with comments:
+
+If you find such string in a .js file - you must manually fix comments in this file.
+(It is expected that you shouldn't have such problems)
+
+5) Go to the gerrit root folder and run
+npm run eslintfix
+
+(If you are doing it for the first time, run the following command before in gerrit root folder:
+npm run install)
+
+Fix error after eslintfix (if exists)
+
+6) If you are doing conversion for the whole project, make the followin changes:
+
+a) Add
+<link rel="import" href="../../../types/polymer-behaviors.js">
+to
+polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html
+
+b) Update polymer.json with the following rules:
+  "lint": {
+    "rules": ["polymer-2"],
+    "ignoreWarnings": ["deprecated-dom-call"]
+  }
+
+
+
+5) Commit changed files.
+
+6) You can update excluded files later.
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/funcToClassBasedElementConverter.ts b/tools/polygerrit-updater/src/funcToClassConversion/funcToClassBasedElementConverter.ts
new file mode 100644
index 0000000..b92a6e9
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/funcToClassBasedElementConverter.ts
@@ -0,0 +1,131 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {LegacyLifecycleMethodsArray, LegacyPolymerComponent} from './polymerComponentParser';
+import {LifecycleMethodsBuilder} from './lifecycleMethodsBuilder';
+import {ClassBasedPolymerElement, PolymerElementBuilder} from './polymerElementBuilder';
+import * as codeUtils from '../utils/codeUtils';
+import * as ts from 'typescript';
+
+export class PolymerFuncToClassBasedConverter {
+  public static convert(component: LegacyPolymerComponent): ClassBasedPolymerElement {
+    const legacySettings = component.componentSettings;
+    const reservedDeclarations = legacySettings.reservedDeclarations;
+
+    if(!reservedDeclarations.is) {
+      throw new Error("Legacy component doesn't have 'is' property");
+    }
+    const className = this.generateClassNameFromTagName(reservedDeclarations.is.data);
+    const updater = new PolymerElementBuilder(component, className);
+    updater.addIsAccessor(reservedDeclarations.is.data);
+
+    if(reservedDeclarations.properties) {
+      updater.addPolymerPropertiesAccessor(reservedDeclarations.properties);
+    }
+
+    updater.addMixin("Polymer.Element");
+    updater.addMixin("Polymer.LegacyElementMixin");
+    updater.addMixin("Polymer.GestureEventListeners");
+
+    if(reservedDeclarations._legacyUndefinedCheck) {
+      updater.addMixin("Polymer.LegacyDataMixin");
+    }
+
+    if(reservedDeclarations.behaviors) {
+      updater.addMixin("Polymer.mixinBehaviors", [reservedDeclarations.behaviors.data]);
+      const mixinNames = this.getMixinNamesFromBehaviors(reservedDeclarations.behaviors.data);
+      const jsDocLines = mixinNames.map(mixinName => {
+        return `@appliesMixin ${mixinName}`;
+      });
+      updater.addClassJSDocComments(jsDocLines);
+    }
+
+    if(reservedDeclarations.observers) {
+      updater.addPolymerPropertiesObservers(reservedDeclarations.observers.data);
+    }
+
+    if(reservedDeclarations.keyBindings) {
+      updater.addKeyBindings(reservedDeclarations.keyBindings.data);
+    }
+
+
+    const lifecycleBuilder = new LifecycleMethodsBuilder();
+    if (reservedDeclarations.listeners) {
+      lifecycleBuilder.addListeners(reservedDeclarations.listeners.data, legacySettings.ordinaryMethods);
+    }
+
+    if (reservedDeclarations.hostAttributes) {
+      lifecycleBuilder.addHostAttributes(reservedDeclarations.hostAttributes.data);
+    }
+
+    for(const name of LegacyLifecycleMethodsArray) {
+      const existingMethod = legacySettings.lifecycleMethods.get(name);
+      if(existingMethod) {
+        lifecycleBuilder.addLegacyLifecycleMethod(name, existingMethod)
+      }
+    }
+
+    const newLifecycleMethods = lifecycleBuilder.buildNewMethods();
+    updater.addLifecycleMethods(newLifecycleMethods);
+
+
+    updater.addOrdinaryMethods(legacySettings.ordinaryMethods);
+    updater.addOrdinaryGetAccessors(legacySettings.ordinaryGetAccessors);
+    updater.addOrdinaryShorthandProperties(legacySettings.ordinaryShorthandProperties);
+    updater.addOrdinaryPropertyAssignments(legacySettings.ordinaryPropertyAssignments);
+
+    return updater.build();
+  }
+
+  private static generateClassNameFromTagName(tagName: string) {
+    let result = "";
+    let nextUppercase = true;
+    for(const ch of tagName) {
+      if (ch === '-') {
+        nextUppercase = true;
+        continue;
+      }
+      result += nextUppercase ? ch.toUpperCase() : ch;
+      nextUppercase = false;
+    }
+    return result;
+  }
+
+  private static getMixinNamesFromBehaviors(behaviors: ts.ArrayLiteralExpression): string[] {
+    return behaviors.elements.map((expression) => {
+      const propertyAccessExpression = codeUtils.assertNodeKind(expression, ts.SyntaxKind.PropertyAccessExpression) as ts.PropertyAccessExpression;
+      const namespaceName = codeUtils.assertNodeKind(propertyAccessExpression.expression, ts.SyntaxKind.Identifier) as ts.Identifier;
+      const behaviorName = propertyAccessExpression.name;
+      if(namespaceName.text === 'Gerrit') {
+        let behaviorNameText = behaviorName.text;
+        const suffix = 'Behavior';
+        if(behaviorNameText.endsWith(suffix)) {
+          behaviorNameText =
+              behaviorNameText.substr(0, behaviorNameText.length - suffix.length);
+        }
+        const mixinName = behaviorNameText + 'Mixin';
+        return `${namespaceName.text}.${mixinName}`
+      } else if(namespaceName.text === 'Polymer') {
+        let behaviorNameText = behaviorName.text;
+        if(behaviorNameText === "IronFitBehavior") {
+          return "Polymer.IronFitMixin";
+        } else if(behaviorNameText === "IronOverlayBehavior") {
+          return "";
+        }
+        throw new Error(`Unsupported behavior: ${propertyAccessExpression.getText()}`);
+      }
+      throw new Error(`Unsupported behavior name ${expression.getFullText()}`)
+    }).filter(name => name.length > 0);
+  }
+}
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/legacyPolymerFuncReplacer.ts b/tools/polygerrit-updater/src/funcToClassConversion/legacyPolymerFuncReplacer.ts
new file mode 100644
index 0000000..57b7b8d
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/legacyPolymerFuncReplacer.ts
@@ -0,0 +1,74 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as ts from 'typescript';
+import * as codeUtils from '../utils/codeUtils'
+import {LegacyPolymerComponent} from './polymerComponentParser';
+import {ClassBasedPolymerElement} from './polymerElementBuilder';
+
+export class LegacyPolymerFuncReplaceResult {
+  public constructor(
+      private readonly transformationResult: ts.TransformationResult<ts.SourceFile>,
+      public readonly leadingComments: string[]) {
+  }
+  public get file(): ts.SourceFile {
+    return this.transformationResult.transformed[0];
+  }
+  public dispose() {
+    this.transformationResult.dispose();
+  }
+
+}
+
+export class LegacyPolymerFuncReplacer {
+  private readonly callStatement: ts.ExpressionStatement;
+  private readonly parentBlock: ts.Block;
+  private readonly callStatementIndexInBlock: number;
+  public constructor(private readonly legacyComponent: LegacyPolymerComponent) {
+    this.callStatement = codeUtils.assertNodeKind(legacyComponent.polymerFuncCallExpr.parent, ts.SyntaxKind.ExpressionStatement);
+    this.parentBlock = codeUtils.assertNodeKind(this.callStatement.parent, ts.SyntaxKind.Block);
+    this.callStatementIndexInBlock = this.parentBlock.statements.indexOf(this.callStatement);
+    if(this.callStatementIndexInBlock < 0) {
+      throw new Error("Internal error! Couldn't find statement in its own parent");
+    }
+  }
+  public replace(classBasedElement: ClassBasedPolymerElement): LegacyPolymerFuncReplaceResult {
+    const classDeclarationWithComments = this.appendLeadingCommentToClassDeclaration(classBasedElement.classDeclaration);
+    return new LegacyPolymerFuncReplaceResult(
+        this.replaceLegacyPolymerFunction(classDeclarationWithComments.classDeclarationWithCommentsPlaceholder, classBasedElement.componentRegistration),
+        classDeclarationWithComments.leadingComments);
+  }
+  private appendLeadingCommentToClassDeclaration(classDeclaration: ts.ClassDeclaration): {classDeclarationWithCommentsPlaceholder: ts.ClassDeclaration, leadingComments: string[]} {
+    const text = this.callStatement.getFullText();
+    let classDeclarationWithCommentsPlaceholder = classDeclaration;
+    const leadingComments: string[] = [];
+    ts.forEachLeadingCommentRange(text, 0, (pos, end, kind, hasTrailingNewLine) => {
+      classDeclarationWithCommentsPlaceholder = codeUtils.addReplacableCommentBeforeNode(classDeclarationWithCommentsPlaceholder, String(leadingComments.length));
+      leadingComments.push(text.substring(pos, end));
+    });
+    return {
+      classDeclarationWithCommentsPlaceholder: classDeclarationWithCommentsPlaceholder,
+      leadingComments: leadingComments
+    }
+  }
+  private replaceLegacyPolymerFunction(classDeclaration: ts.ClassDeclaration, componentRegistration: ts.ExpressionStatement): ts.TransformationResult<ts.SourceFile> {
+    const newStatements = Array.from(this.parentBlock.statements);
+    newStatements.splice(this.callStatementIndexInBlock, 1, classDeclaration, componentRegistration);
+
+    const updatedBlock = ts.getMutableClone(this.parentBlock);
+    updatedBlock.statements = ts.createNodeArray(newStatements);
+    return codeUtils.replaceNode(this.legacyComponent.parsedFile, this.parentBlock, updatedBlock);
+
+  }
+}
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/lifecycleMethodsBuilder.ts b/tools/polygerrit-updater/src/funcToClassConversion/lifecycleMethodsBuilder.ts
new file mode 100644
index 0000000..e9e13f5
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/lifecycleMethodsBuilder.ts
@@ -0,0 +1,140 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as ts from 'typescript';
+import * as codeUtils from '../utils/codeUtils';
+import {LegacyLifecycleMethodName, OrdinaryMethods} from './polymerComponentParser';
+
+interface LegacyLifecycleMethodContent {
+  codeAtMethodStart: ts.Statement[];
+  existingMethod?: ts.MethodDeclaration;
+  codeAtMethodEnd: ts.Statement[];
+}
+
+export interface LifecycleMethod {
+  originalPos: number;//-1 - no original method exists
+  method: ts.MethodDeclaration;
+  name: LegacyLifecycleMethodName;
+}
+
+export class LifecycleMethodsBuilder {
+  private readonly methods: Map<LegacyLifecycleMethodName, LegacyLifecycleMethodContent> = new Map();
+
+  private getMethodContent(name: LegacyLifecycleMethodName): LegacyLifecycleMethodContent {
+    if(!this.methods.has(name)) {
+      this.methods.set(name, {
+        codeAtMethodStart: [],
+        codeAtMethodEnd: []
+      });
+    }
+    return this.methods.get(name)!;
+  }
+
+  public addListeners(legacyListeners: ts.ObjectLiteralExpression, legacyOrdinaryMethods: OrdinaryMethods) {
+    for(const listener of legacyListeners.properties) {
+      const propertyAssignment = codeUtils.assertNodeKind(listener, ts.SyntaxKind.PropertyAssignment) as ts.PropertyAssignment;
+      if(!propertyAssignment.name) {
+        throw new Error("Listener must have event name");
+      }
+      let eventNameLiteral: ts.StringLiteral;
+      let commentsToRestore: string[] = [];
+      if(propertyAssignment.name.kind === ts.SyntaxKind.StringLiteral) {
+        //We don't loose comment in this case, because we keep literal as is
+        eventNameLiteral = propertyAssignment.name;
+      } else if(propertyAssignment.name.kind === ts.SyntaxKind.Identifier) {
+        eventNameLiteral = ts.createStringLiteral(propertyAssignment.name.text);
+        commentsToRestore = codeUtils.getLeadingComments(propertyAssignment);
+      } else {
+        throw new Error(`Unsupported type ${ts.SyntaxKind[propertyAssignment.name.kind]}`);
+      }
+
+      const handlerLiteral = codeUtils.assertNodeKind(propertyAssignment.initializer, ts.SyntaxKind.StringLiteral) as ts.StringLiteral;
+      const handlerImpl = legacyOrdinaryMethods.get(handlerLiteral.text);
+      if(!handlerImpl) {
+        throw new Error(`Can't find event handler '${handlerLiteral.text}'`);
+      }
+      const eventHandlerAccess = ts.createPropertyAccess(ts.createThis(), handlerLiteral.text);
+      //ts.forEachChild(handler)
+      const args: ts.Identifier[] = handlerImpl.parameters.map((arg) => codeUtils.assertNodeKind(arg.name, ts.SyntaxKind.Identifier));
+      const eventHandlerCall = ts.createCall(eventHandlerAccess, [], args);
+      let arrowFunc = ts.createArrowFunction([], [], handlerImpl.parameters, undefined, undefined, eventHandlerCall);
+      arrowFunc = codeUtils.addNewLineBeforeNode(arrowFunc);
+
+      const methodContent = this.getMethodContent("created");
+      //See https://polymer-library.polymer-project.org/3.0/docs/devguide/gesture-events for a list of events
+      if(["down", "up", "tap", "track"].indexOf(eventNameLiteral.text) >= 0) {
+        const methodCall = ts.createCall(codeUtils.createNameExpression("Polymer.Gestures.addListener"), [], [ts.createThis(), eventNameLiteral, arrowFunc]);
+        methodContent.codeAtMethodEnd.push(ts.createExpressionStatement(methodCall));
+      }
+      else {
+        let methodCall = ts.createCall(ts.createPropertyAccess(ts.createThis(), "addEventListener"), [], [eventNameLiteral, arrowFunc]);
+        methodCall = codeUtils.restoreLeadingComments(methodCall, commentsToRestore);
+        methodContent.codeAtMethodEnd.push(ts.createExpressionStatement(methodCall));
+      }
+    }
+  }
+
+  public addHostAttributes(legacyHostAttributes: ts.ObjectLiteralExpression) {
+    for(const listener of legacyHostAttributes.properties) {
+      const propertyAssignment = codeUtils.assertNodeKind(listener, ts.SyntaxKind.PropertyAssignment) as ts.PropertyAssignment;
+      if(!propertyAssignment.name) {
+        throw new Error("Listener must have event name");
+      }
+      let attributeNameLiteral: ts.StringLiteral;
+      if(propertyAssignment.name.kind === ts.SyntaxKind.StringLiteral) {
+        attributeNameLiteral = propertyAssignment.name;
+      } else if(propertyAssignment.name.kind === ts.SyntaxKind.Identifier) {
+        attributeNameLiteral = ts.createStringLiteral(propertyAssignment.name.text);
+      } else {
+        throw new Error(`Unsupported type ${ts.SyntaxKind[propertyAssignment.name.kind]}`);
+      }
+      let attributeValueLiteral: ts.StringLiteral | ts.NumericLiteral;
+      if(propertyAssignment.initializer.kind === ts.SyntaxKind.StringLiteral) {
+        attributeValueLiteral = propertyAssignment.initializer as ts.StringLiteral;
+      } else if(propertyAssignment.initializer.kind === ts.SyntaxKind.NumericLiteral) {
+        attributeValueLiteral = propertyAssignment.initializer as ts.NumericLiteral;
+      } else {
+        throw new Error(`Unsupported type ${ts.SyntaxKind[propertyAssignment.initializer.kind]}`);
+      }
+      const methodCall = ts.createCall(ts.createPropertyAccess(ts.createThis(), "_ensureAttribute"), [], [attributeNameLiteral, attributeValueLiteral]);
+      this.getMethodContent("ready").codeAtMethodEnd.push(ts.createExpressionStatement(methodCall));
+    }
+  }
+
+  public addLegacyLifecycleMethod(name: LegacyLifecycleMethodName, method: ts.MethodDeclaration) {
+    const content = this.getMethodContent(name);
+    if(content.existingMethod) {
+      throw new Error(`Legacy lifecycle method ${name} already added`);
+    }
+    content.existingMethod = method;
+  }
+
+  public buildNewMethods(): LifecycleMethod[] {
+    const result = [];
+    for(const [name, content] of this.methods) {
+      const newMethod = this.createLifecycleMethod(name, content.existingMethod, content.codeAtMethodStart, content.codeAtMethodEnd);
+      if(!newMethod) continue;
+      result.push({
+        name,
+        originalPos: content.existingMethod ? content.existingMethod.pos : -1,
+        method: newMethod
+      })
+    }
+    return result;
+  }
+
+  private createLifecycleMethod(name: string, methodDecl: ts.MethodDeclaration | undefined, codeAtStart: ts.Statement[], codeAtEnd: ts.Statement[]): ts.MethodDeclaration | undefined {
+    return codeUtils.createMethod(name, methodDecl, codeAtStart, codeAtEnd, true);
+  }
+}
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/polymerComponentParser.ts b/tools/polygerrit-updater/src/funcToClassConversion/polymerComponentParser.ts
new file mode 100644
index 0000000..6006608
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/polymerComponentParser.ts
@@ -0,0 +1,301 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as ts from "typescript";
+import * as fs from "fs";
+import * as path from "path";
+import { unexpectedValue } from "../utils/unexpectedValue";
+import * as codeUtils from "../utils/codeUtils";
+import {CommentsParser} from '../utils/commentsParser';
+
+export class LegacyPolymerComponentParser {
+  public constructor(private readonly rootDir: string, private readonly htmlFiles: Set<string>) {
+  }
+  public async parse(jsFile: string): Promise<ParsedPolymerComponent | null> {
+    const sourceFile: ts.SourceFile  = this.parseJsFile(jsFile);
+    const legacyComponent = this.tryParseLegacyComponent(sourceFile);
+    if (legacyComponent) {
+      return legacyComponent;
+    }
+    return null;
+  }
+  private parseJsFile(jsFile: string): ts.SourceFile {
+    return ts.createSourceFile(jsFile, fs.readFileSync(path.resolve(this.rootDir, jsFile)).toString(), ts.ScriptTarget.ES2015, true);
+  }
+
+  private tryParseLegacyComponent(sourceFile: ts.SourceFile): ParsedPolymerComponent | null {
+    const polymerFuncCalls: ts.CallExpression[] = [];
+
+    function addPolymerFuncCall(node: ts.Node) {
+      if(node.kind === ts.SyntaxKind.CallExpression) {
+        const callExpression: ts.CallExpression = node as ts.CallExpression;
+        if(callExpression.expression.kind === ts.SyntaxKind.Identifier) {
+          const identifier = callExpression.expression as ts.Identifier;
+          if(identifier.text === "Polymer") {
+            polymerFuncCalls.push(callExpression);
+          }
+        }
+      }
+      ts.forEachChild(node, addPolymerFuncCall);
+    }
+
+    addPolymerFuncCall(sourceFile);
+
+
+    if (polymerFuncCalls.length === 0) {
+      return null;
+    }
+    if (polymerFuncCalls.length > 1) {
+      throw new Error("Each .js file must contain only one Polymer component");
+    }
+    const parsedPath = path.parse(sourceFile.fileName);
+    const htmlFullPath = path.format({
+      dir: parsedPath.dir,
+      name: parsedPath.name,
+      ext: ".html"
+    });
+    if (!this.htmlFiles.has(htmlFullPath)) {
+      throw new Error("Legacy .js component dosn't have associated .html file");
+    }
+
+    const polymerFuncCall = polymerFuncCalls[0];
+    if(polymerFuncCall.arguments.length !== 1) {
+      throw new Error("The Polymer function must be called with exactly one parameter");
+    }
+    const argument = polymerFuncCall.arguments[0];
+    if(argument.kind !== ts.SyntaxKind.ObjectLiteralExpression) {
+      throw new Error("The parameter for Polymer function must be ObjectLiteralExpression (i.e. '{...}')");
+    }
+    const infoArg = argument as ts.ObjectLiteralExpression;
+
+    return {
+      jsFile: sourceFile.fileName,
+      htmlFile: htmlFullPath,
+      parsedFile: sourceFile,
+      polymerFuncCallExpr: polymerFuncCalls[0],
+      componentSettings: this.parseLegacyComponentSettings(infoArg),
+    };
+  }
+
+  private parseLegacyComponentSettings(info: ts.ObjectLiteralExpression): LegacyPolymerComponentSettings {
+    const props: Map<string, ts.ObjectLiteralElementLike> = new Map();
+    for(const property of info.properties) {
+      const name = property.name;
+      if (name === undefined) {
+        throw new Error("Property name is not defined");
+      }
+      switch(name.kind) {
+        case ts.SyntaxKind.Identifier:
+        case ts.SyntaxKind.StringLiteral:
+          if (props.has(name.text)) {
+            throw new Error(`Property ${name.text} appears more than once`);
+          }
+          props.set(name.text, property);
+          break;
+        case ts.SyntaxKind.ComputedPropertyName:
+          continue;
+        default:
+          unexpectedValue(ts.SyntaxKind[name.kind]);
+      }
+    }
+
+    if(props.has("_noAccessors")) {
+      throw new Error("_noAccessors is not supported");
+    }
+
+    const legacyLifecycleMethods: LegacyLifecycleMethods = new Map();
+    for(const name of LegacyLifecycleMethodsArray) {
+      const methodDecl = this.getLegacyMethodDeclaration(props, name);
+      if(methodDecl) {
+        legacyLifecycleMethods.set(name, methodDecl);
+      }
+    }
+
+    const ordinaryMethods: OrdinaryMethods = new Map();
+    const ordinaryShorthandProperties: OrdinaryShorthandProperties = new Map();
+    const ordinaryGetAccessors: OrdinaryGetAccessors = new Map();
+    const ordinaryPropertyAssignments: OrdinaryPropertyAssignments = new Map();
+    for(const [name, val] of props) {
+      if(RESERVED_NAMES.hasOwnProperty(name)) continue;
+      switch(val.kind) {
+        case ts.SyntaxKind.MethodDeclaration:
+          ordinaryMethods.set(name, val as ts.MethodDeclaration);
+          break;
+        case ts.SyntaxKind.ShorthandPropertyAssignment:
+          ordinaryShorthandProperties.set(name, val as ts.ShorthandPropertyAssignment);
+          break;
+        case ts.SyntaxKind.GetAccessor:
+          ordinaryGetAccessors.set(name, val as ts.GetAccessorDeclaration);
+          break;
+        case ts.SyntaxKind.PropertyAssignment:
+          ordinaryPropertyAssignments.set(name, val as ts.PropertyAssignment);
+          break;
+        default:
+          throw new Error(`Unsupported element kind: ${ts.SyntaxKind[val.kind]}`);
+      }
+      //ordinaryMethods.set(name, tsUtils.assertNodeKind(val, ts.SyntaxKind.MethodDeclaration) as ts.MethodDeclaration);
+    }
+
+    const eventsComments: string[] = this.getEventsComments(info.getFullText());
+
+    return {
+      reservedDeclarations: {
+        is: this.getStringLiteralValueWithComments(this.getLegacyPropertyInitializer(props, "is")),
+        _legacyUndefinedCheck: this.getBooleanLiteralValueWithComments(this.getLegacyPropertyInitializer(props, "_legacyUndefinedCheck")),
+        properties: this.getObjectLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "properties")),
+        behaviors: this.getArrayLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "behaviors")),
+        observers: this.getArrayLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "observers")),
+        listeners: this.getObjectLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "listeners")),
+        hostAttributes: this.getObjectLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "hostAttributes")),
+        keyBindings: this.getObjectLiteralExpressionWithComments(this.getLegacyPropertyInitializer(props, "keyBindings")),
+      },
+      eventsComments: eventsComments,
+      lifecycleMethods: legacyLifecycleMethods,
+      ordinaryMethods: ordinaryMethods,
+      ordinaryShorthandProperties: ordinaryShorthandProperties,
+      ordinaryGetAccessors: ordinaryGetAccessors,
+      ordinaryPropertyAssignments: ordinaryPropertyAssignments,
+    };
+  }
+
+  private convertLegacyProeprtyInitializer<T>(initializer: LegacyPropertyInitializer | undefined, converter: (exp: ts.Expression) => T): DataWithComments<T> | undefined {
+    if(!initializer) {
+      return undefined;
+    }
+    return {
+      data: converter(initializer.data),
+      leadingComments: initializer.leadingComments,
+    }
+  }
+
+  private getObjectLiteralExpressionWithComments(initializer: LegacyPropertyInitializer | undefined): DataWithComments<ts.ObjectLiteralExpression> | undefined {
+    return this.convertLegacyProeprtyInitializer(initializer,
+        expr => codeUtils.getObjectLiteralExpression(expr));
+  }
+
+  private getStringLiteralValueWithComments(initializer: LegacyPropertyInitializer | undefined): DataWithComments<string> | undefined {
+    return this.convertLegacyProeprtyInitializer(initializer,
+        expr => codeUtils.getStringLiteralValue(expr));
+  }
+
+  private getBooleanLiteralValueWithComments(initializer: LegacyPropertyInitializer | undefined): DataWithComments<boolean> | undefined {
+    return this.convertLegacyProeprtyInitializer(initializer,
+        expr => codeUtils.getBooleanLiteralValue(expr));
+  }
+
+
+  private getArrayLiteralExpressionWithComments(initializer: LegacyPropertyInitializer | undefined): DataWithComments<ts.ArrayLiteralExpression> | undefined {
+    return this.convertLegacyProeprtyInitializer(initializer,
+        expr => codeUtils.getArrayLiteralExpression(expr));
+  }
+
+  private getLegacyPropertyInitializer(props: Map<String, ts.ObjectLiteralElementLike>, propName: string): LegacyPropertyInitializer | undefined {
+    const property = props.get(propName);
+    if (!property) {
+      return undefined;
+    }
+    const assignment = codeUtils.getPropertyAssignment(property);
+    if (!assignment) {
+      return undefined;
+    }
+    const comments: string[] = codeUtils.getLeadingComments(property)
+          .filter(c => !this.isEventComment(c));
+    return {
+      data: assignment.initializer,
+      leadingComments: comments,
+    };
+  }
+
+  private isEventComment(comment: string): boolean {
+    return comment.indexOf('@event') >= 0;
+  }
+
+  private getEventsComments(polymerComponentSource: string): string[] {
+    return CommentsParser.collectAllComments(polymerComponentSource)
+        .filter(c => this.isEventComment(c));
+  }
+
+  private getLegacyMethodDeclaration(props: Map<String, ts.ObjectLiteralElementLike>, propName: string): ts.MethodDeclaration | undefined {
+    const property = props.get(propName);
+    if (!property) {
+      return undefined;
+    }
+    return codeUtils.assertNodeKind(property, ts.SyntaxKind.MethodDeclaration) as ts.MethodDeclaration;
+  }
+
+}
+
+export type ParsedPolymerComponent = LegacyPolymerComponent;
+
+export interface LegacyPolymerComponent {
+  jsFile: string;
+  htmlFile: string;
+  parsedFile: ts.SourceFile;
+  polymerFuncCallExpr: ts.CallExpression;
+  componentSettings: LegacyPolymerComponentSettings;
+}
+
+export interface LegacyReservedDeclarations {
+  is?: DataWithComments<string>;
+  _legacyUndefinedCheck?: DataWithComments<boolean>;
+  properties?: DataWithComments<ts.ObjectLiteralExpression>;
+  behaviors?: DataWithComments<ts.ArrayLiteralExpression>,
+  observers? :DataWithComments<ts.ArrayLiteralExpression>,
+  listeners? :DataWithComments<ts.ObjectLiteralExpression>,
+  hostAttributes?: DataWithComments<ts.ObjectLiteralExpression>,
+  keyBindings?: DataWithComments<ts.ObjectLiteralExpression>,
+}
+
+export const LegacyLifecycleMethodsArray = <const>["beforeRegister", "registered", "created", "ready", "attached" , "detached", "attributeChanged"];
+export type LegacyLifecycleMethodName = typeof LegacyLifecycleMethodsArray[number];
+export type LegacyLifecycleMethods = Map<LegacyLifecycleMethodName, ts.MethodDeclaration>;
+export type OrdinaryMethods = Map<string, ts.MethodDeclaration>;
+export type OrdinaryShorthandProperties = Map<string, ts.ShorthandPropertyAssignment>;
+export type OrdinaryGetAccessors = Map<string, ts.GetAccessorDeclaration>;
+export type OrdinaryPropertyAssignments = Map<string, ts.PropertyAssignment>;
+export type ReservedName = LegacyLifecycleMethodName | keyof LegacyReservedDeclarations;
+export const RESERVED_NAMES: {[x in ReservedName]: boolean} = {
+  attached: true,
+  detached: true,
+  ready: true,
+  created: true,
+  beforeRegister: true,
+  registered: true,
+  attributeChanged: true,
+  is: true,
+  _legacyUndefinedCheck: true,
+  properties: true,
+  behaviors: true,
+  observers: true,
+  listeners: true,
+  hostAttributes: true,
+  keyBindings: true,
+};
+
+export interface LegacyPolymerComponentSettings {
+  reservedDeclarations: LegacyReservedDeclarations;
+  lifecycleMethods: LegacyLifecycleMethods,
+  ordinaryMethods: OrdinaryMethods,
+  ordinaryShorthandProperties: OrdinaryShorthandProperties,
+  ordinaryGetAccessors: OrdinaryGetAccessors,
+  ordinaryPropertyAssignments: OrdinaryPropertyAssignments,
+  eventsComments: string[];
+}
+
+export interface DataWithComments<T> {
+  data: T;
+  leadingComments: string[];
+}
+
+type LegacyPropertyInitializer = DataWithComments<ts.Expression>;
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/polymerElementBuilder.ts b/tools/polygerrit-updater/src/funcToClassConversion/polymerElementBuilder.ts
new file mode 100644
index 0000000..d6e113c
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/polymerElementBuilder.ts
@@ -0,0 +1,142 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {DataWithComments, LegacyPolymerComponent, LegacyReservedDeclarations, OrdinaryGetAccessors, OrdinaryMethods, OrdinaryPropertyAssignments, OrdinaryShorthandProperties} from './polymerComponentParser';
+import * as ts from 'typescript';
+import * as codeUtils from '../utils/codeUtils';
+import {LifecycleMethod} from './lifecycleMethodsBuilder';
+import {PolymerClassBuilder} from '../utils/polymerClassBuilder';
+import {SyntaxKind} from 'typescript';
+
+export interface ClassBasedPolymerElement {
+  classDeclaration: ts.ClassDeclaration;
+  componentRegistration: ts.ExpressionStatement;
+  eventsComments: string[];
+  generatedComments: string[];
+}
+
+export class PolymerElementBuilder {
+  private readonly reservedDeclarations: LegacyReservedDeclarations;
+  private readonly classBuilder: PolymerClassBuilder;
+  private mixins: ts.ExpressionWithTypeArguments | null;
+
+  public constructor(private readonly legacyComponent: LegacyPolymerComponent, className: string) {
+    this.reservedDeclarations = legacyComponent.componentSettings.reservedDeclarations;
+    this.classBuilder = new PolymerClassBuilder(className);
+    this.mixins = null;
+  }
+
+  public addIsAccessor(tagName: string) {
+    this.classBuilder.addIsAccessor(this.createIsAccessor(tagName));
+  }
+
+  public addPolymerPropertiesAccessor(legacyProperties: DataWithComments<ts.ObjectLiteralExpression>) {
+    const returnStatement = ts.createReturn(legacyProperties.data);
+    const block = ts.createBlock([returnStatement]);
+    let propertiesAccessor = ts.createGetAccessor(undefined, [ts.createModifier(ts.SyntaxKind.StaticKeyword)], "properties", [], undefined, block);
+    if(legacyProperties.leadingComments.length > 0) {
+      propertiesAccessor = codeUtils.restoreLeadingComments(propertiesAccessor, legacyProperties.leadingComments);
+    }
+    this.classBuilder.addPolymerPropertiesAccessor(legacyProperties.data.pos, propertiesAccessor);
+  }
+
+  public addPolymerPropertiesObservers(legacyObservers: ts.ArrayLiteralExpression) {
+    const returnStatement = ts.createReturn(legacyObservers);
+    const block = ts.createBlock([returnStatement]);
+    const propertiesAccessor = ts.createGetAccessor(undefined, [ts.createModifier(ts.SyntaxKind.StaticKeyword)], "observers", [], undefined, block);
+
+    this.classBuilder.addPolymerObserversAccessor(legacyObservers.pos, propertiesAccessor);
+  }
+
+  public addKeyBindings(keyBindings: ts.ObjectLiteralExpression) {
+    //In Polymer 2 keyBindings must be a property with get accessor
+    const returnStatement = ts.createReturn(keyBindings);
+    const block = ts.createBlock([returnStatement]);
+    const keyBindingsAccessor = ts.createGetAccessor(undefined, [], "keyBindings", [], undefined, block);
+
+    this.classBuilder.addGetAccessor(keyBindings.pos, keyBindingsAccessor);
+  }
+  public addOrdinaryMethods(ordinaryMethods: OrdinaryMethods) {
+    for(const [name, method] of ordinaryMethods) {
+      this.classBuilder.addMethod(method.pos, method);
+    }
+  }
+
+  public addOrdinaryGetAccessors(ordinaryGetAccessors: OrdinaryGetAccessors) {
+    for(const [name, accessor] of ordinaryGetAccessors) {
+      this.classBuilder.addGetAccessor(accessor.pos, accessor);
+    }
+  }
+
+  public addOrdinaryShorthandProperties(ordinaryShorthandProperties: OrdinaryShorthandProperties) {
+    for (const [name, property] of ordinaryShorthandProperties) {
+      this.classBuilder.addClassFieldInitializer(property.name, property.name);
+    }
+  }
+
+  public addOrdinaryPropertyAssignments(ordinaryPropertyAssignments: OrdinaryPropertyAssignments) {
+    for (const [name, property] of ordinaryPropertyAssignments) {
+      const propertyName = codeUtils.assertNodeKind(property.name, ts.SyntaxKind.Identifier) as ts.Identifier;
+      this.classBuilder.addClassFieldInitializer(propertyName, property.initializer);
+    }
+  }
+
+  public addMixin(name: string, mixinArguments?: ts.Expression[]) {
+    let fullMixinArguments: ts.Expression[] = [];
+    if(mixinArguments) {
+      fullMixinArguments.push(...mixinArguments);
+    }
+    if(this.mixins) {
+      fullMixinArguments.push(this.mixins.expression);
+    }
+    if(fullMixinArguments.length > 0) {
+      this.mixins = ts.createExpressionWithTypeArguments([], ts.createCall(codeUtils.createNameExpression(name), [], fullMixinArguments.length > 0 ? fullMixinArguments : undefined));
+    }
+    else {
+      this.mixins = ts.createExpressionWithTypeArguments([], codeUtils.createNameExpression(name));
+    }
+  }
+
+  public addClassJSDocComments(lines: string[]) {
+    this.classBuilder.addClassJSDocComments(lines);
+  }
+
+  public build(): ClassBasedPolymerElement {
+    if(this.mixins) {
+      this.classBuilder.setBaseType(this.mixins);
+    }
+    const className = this.classBuilder.className;
+    const callExpression = ts.createCall(ts.createPropertyAccess(ts.createIdentifier("customElements"), "define"), undefined, [ts.createPropertyAccess(ts.createIdentifier(className), "is"), ts.createIdentifier(className)]);
+    const classBuilderResult = this.classBuilder.build();
+    return {
+      classDeclaration: classBuilderResult.classDeclaration,
+      generatedComments: classBuilderResult.generatedComments,
+      componentRegistration: ts.createExpressionStatement(callExpression),
+      eventsComments: this.legacyComponent.componentSettings.eventsComments,
+    };
+  }
+
+  private createIsAccessor(tagName: string): ts.GetAccessorDeclaration {
+    const returnStatement = ts.createReturn(ts.createStringLiteral(tagName));
+    const block = ts.createBlock([returnStatement]);
+    const accessor = ts.createGetAccessor([], [ts.createModifier(ts.SyntaxKind.StaticKeyword)], "is", [], undefined, block);
+    return codeUtils.addReplacableCommentAfterNode(accessor, "eventsComments");
+  }
+
+  public addLifecycleMethods(newLifecycleMethods: LifecycleMethod[]) {
+    for(const lifecycleMethod of newLifecycleMethods) {
+      this.classBuilder.addLifecycleMethod(lifecycleMethod.name, lifecycleMethod.originalPos, lifecycleMethod.method);
+    }
+  }
+}
diff --git a/tools/polygerrit-updater/src/funcToClassConversion/updatedFileWriter.ts b/tools/polygerrit-updater/src/funcToClassConversion/updatedFileWriter.ts
new file mode 100644
index 0000000..a147f50
--- /dev/null
+++ b/tools/polygerrit-updater/src/funcToClassConversion/updatedFileWriter.ts
@@ -0,0 +1,248 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import {LegacyPolymerComponent} from './polymerComponentParser';
+import * as ts from 'typescript';
+import * as codeUtils from '../utils/codeUtils';
+import * as path from "path";
+import * as fs from "fs";
+import {LegacyPolymerFuncReplaceResult} from './legacyPolymerFuncReplacer';
+import {CommentsParser} from '../utils/commentsParser';
+
+export interface UpdatedFileWriterParameters {
+  out: string;
+  inplace: boolean;
+  writeOutput: boolean;
+  rootDir: string;
+}
+
+interface Replacement {
+  start: number;
+  length: number;
+  newText: string;
+}
+
+const elementRegistrationRegex = /^(\s*)customElements.define\((\w+).is, \w+\);$/m;
+const maxLineLength = 80;
+
+export class UpdatedFileWriter {
+  public constructor(private readonly component: LegacyPolymerComponent, private readonly params: UpdatedFileWriterParameters) {
+  }
+
+  public write(replaceResult: LegacyPolymerFuncReplaceResult, eventsComments: string[], generatedComments: string[]) {
+    const options: ts.PrinterOptions = {
+      removeComments: false,
+      newLine: ts.NewLineKind.LineFeed,
+    };
+    const printer = ts.createPrinter(options);
+    let newContent = codeUtils.applyNewLines(printer.printFile(replaceResult.file));
+    //ts printer doesn't keep original formatting of the file (spacing, new lines, comments, etc...).
+    //The following code tries restore original formatting
+
+    const existingComments = this.collectAllComments(newContent, []);
+
+    newContent = this.restoreEventsComments(newContent, eventsComments, existingComments);
+    newContent = this.restoreLeadingComments(newContent, replaceResult.leadingComments);
+    newContent = this.restoreFormating(printer, newContent);
+    newContent = this.splitLongLines(newContent);
+    newContent = this.addCommentsWarnings(newContent, generatedComments);
+
+    if (this.params.writeOutput) {
+      const outDir = this.params.inplace ? this.params.rootDir : this.params.out;
+      const fullOutPath = path.resolve(outDir, this.component.jsFile);
+      const fullOutDir = path.dirname(fullOutPath);
+      if (!fs.existsSync(fullOutDir)) {
+        fs.mkdirSync(fullOutDir, {
+          recursive: true,
+          mode: fs.lstatSync(this.params.rootDir).mode
+        });
+      }
+      fs.writeFileSync(fullOutPath, newContent);
+    }
+  }
+
+  private restoreEventsComments(content: string, eventsComments: string[], existingComments: Map<string, number>): string {
+    //In some cases Typescript compiler keep existing comments. These comments
+    // must not be restored here
+    eventsComments = eventsComments.filter(c => !existingComments.has(this.getNormalizedComment(c)));
+    return codeUtils.replaceComment(content, "eventsComments", "\n" + eventsComments.join("\n\n") + "\n");
+  }
+
+  private restoreLeadingComments(content: string, leadingComments: string[]): string {
+    return leadingComments.reduce(
+        (newContent, comment, commentIndex) =>
+            codeUtils.replaceComment(newContent, String(commentIndex), comment),
+        content);
+  }
+
+  private restoreFormating(printer: ts.Printer, newContent: string): string {
+    const originalFile = this.component.parsedFile;
+    const newFile = ts.createSourceFile(originalFile.fileName, newContent, originalFile.languageVersion, true, ts.ScriptKind.JS);
+    const textMap = new Map<ts.SyntaxKind, Map<string, Set<string>>>();
+    const comments = new Set<string>();
+    this.collectAllStrings(printer, originalFile, textMap);
+
+    const replacements: Replacement[] = [];
+    this.collectReplacements(printer, newFile, textMap, replacements);
+    replacements.sort((a, b) => b.start - a.start);
+    let result = newFile.getFullText();
+    let prevReplacement: Replacement | null = null;
+    for (const replacement of replacements) {
+      if (prevReplacement) {
+        if (replacement.start + replacement.length > prevReplacement.start) {
+          throw new Error('Internal error! Replacements must not intersect');
+        }
+      }
+      result = result.substring(0, replacement.start) + replacement.newText + result.substring(replacement.start + replacement.length);
+      prevReplacement = replacement;
+    }
+    return result;
+  }
+
+  private splitLongLines(content: string): string {
+    content = content.replace(elementRegistrationRegex, (match, indent, className) => {
+      if (match.length > maxLineLength) {
+        return `${indent}customElements.define(${className}.is,\n` +
+            `${indent}  ${className});`;
+      }
+      else {
+        return match;
+      }
+    });
+
+    return content
+        .replace(
+            "Polymer.LegacyDataMixin(Polymer.GestureEventListeners(Polymer.LegacyElementMixin(Polymer.Element)))",
+            "Polymer.LegacyDataMixin(\nPolymer.GestureEventListeners(\nPolymer.LegacyElementMixin(\nPolymer.Element)))")
+        .replace(
+            "Polymer.GestureEventListeners(Polymer.LegacyElementMixin(Polymer.Element))",
+            "Polymer.GestureEventListeners(\nPolymer.LegacyElementMixin(\nPolymer.Element))");
+
+  }
+
+  private addCommentsWarnings(newContent: string, generatedComments: string[]): string {
+    const expectedComments = this.collectAllComments(this.component.parsedFile.getFullText(), generatedComments);
+    const newComments = this.collectAllComments(newContent, []);
+    const commentsWarnings = [];
+    for (const [text, count] of expectedComments) {
+      const newCount = newComments.get(text);
+      if (!newCount) {
+        commentsWarnings.push(`Comment '${text}' is missing in the new content.`);
+      }
+      else if (newCount != count) {
+        commentsWarnings.push(`Comment '${text}' appears ${newCount} times in the new file and ${count} times in the old file.`);
+      }
+    }
+
+    for (const [text, newCount] of newComments) {
+      if (!expectedComments.has(text)) {
+        commentsWarnings.push(`Comment '${text}' appears only in the new content`);
+      }
+    }
+    if (commentsWarnings.length === 0) {
+      return newContent;
+    }
+    let commentsProblemStr = "";
+    if (commentsWarnings.length > 0) {
+      commentsProblemStr = commentsWarnings.join("-----------------------------\n");
+      console.log(commentsProblemStr);
+    }
+
+    return "//This file has the following problems with comments:\n" + commentsProblemStr + "\n" + newContent;
+
+  }
+
+  private collectAllComments(content: string, additionalComments: string[]): Map<string, number> {
+    const comments = CommentsParser.collectAllComments(content);
+    comments.push(...additionalComments);
+    const result = new Map<string, number>();
+    for (const comment of comments) {
+      let normalizedComment = this.getNormalizedComment(comment);
+      const count = result.get(normalizedComment);
+      if (count) {
+        result.set(normalizedComment, count + 1);
+      } else {
+        result.set(normalizedComment, 1);
+      }
+    }
+    return result;
+  }
+
+  private getNormalizedComment(comment: string): string {
+    if(comment.startsWith('/**')) {
+      comment = comment.replace(/^\s+\*/gm, "*");
+    }
+    return comment;
+  }
+
+  private collectAllStrings(printer: ts.Printer, node: ts.Node, map: Map<ts.SyntaxKind, Map<string, Set<string>>>) {
+    const formattedText = printer.printNode(ts.EmitHint.Unspecified, node, node.getSourceFile())
+    const originalText = node.getFullText();
+    this.addIfNotExists(map, node.kind, formattedText, originalText);
+    ts.forEachChild(node, child => this.collectAllStrings(printer, child, map));
+  }
+
+  private collectReplacements(printer: ts.Printer, node: ts.Node, map: Map<ts.SyntaxKind, Map<string, Set<string>>>, replacements: Replacement[]) {
+    if(node.kind === ts.SyntaxKind.ThisKeyword || node.kind === ts.SyntaxKind.Identifier || node.kind === ts.SyntaxKind.StringLiteral || node.kind === ts.SyntaxKind.NumericLiteral) {
+      return;
+    }
+    const replacement = this.getReplacement(printer, node, map);
+    if(replacement) {
+      replacements.push(replacement);
+      return;
+    }
+    ts.forEachChild(node, child => this.collectReplacements(printer, child, map, replacements));
+  }
+
+  private addIfNotExists(map: Map<ts.SyntaxKind, Map<string, Set<string>>>, kind: ts.SyntaxKind, formattedText: string, originalText: string) {
+    let mapForKind = map.get(kind);
+    if(!mapForKind) {
+      mapForKind = new Map();
+      map.set(kind, mapForKind);
+    }
+
+    let existingOriginalText = mapForKind.get(formattedText);
+    if(!existingOriginalText) {
+      existingOriginalText = new Set<string>();
+      mapForKind.set(formattedText, existingOriginalText);
+      //throw new Error(`Different formatting of the same string exists. Kind: ${ts.SyntaxKind[kind]}.\nFormatting 1:\n${originalText}\nFormatting2:\n${existingOriginalText}\n `);
+    }
+    existingOriginalText.add(originalText);
+  }
+
+  private getReplacement(printer: ts.Printer, node: ts.Node, map: Map<ts.SyntaxKind, Map<string, Set<string>>>): Replacement | undefined {
+    const replacementsForKind = map.get(node.kind);
+    if(!replacementsForKind) {
+      return;
+    }
+    // Use printer instead of getFullText to "isolate" node content.
+    // node.getFullText returns text with indents from the original file.
+    const newText = printer.printNode(ts.EmitHint.Unspecified, node, node.getSourceFile());
+    const originalSet = replacementsForKind.get(newText);
+    if(!originalSet || originalSet.size === 0) {
+      return;
+    }
+    if(originalSet.size >= 2) {
+      console.log(`Multiple replacements possible. Formatting of some lines can be changed`);
+    }
+    const replacementText: string = originalSet.values().next().value;
+    const nodeText = node.getFullText();
+    return {
+      start: node.pos,
+      length: nodeText.length,//Do not use newText here!
+      newText: replacementText,
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/index.ts b/tools/polygerrit-updater/src/index.ts
new file mode 100644
index 0000000..1b7c315
--- /dev/null
+++ b/tools/polygerrit-updater/src/index.ts
@@ -0,0 +1,168 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as fs from "fs";
+import * as path from "path";
+import {LegacyPolymerComponent, LegacyPolymerComponentParser} from './funcToClassConversion/polymerComponentParser';
+import {ClassBasedPolymerElement} from './funcToClassConversion/polymerElementBuilder';
+import {PolymerFuncToClassBasedConverter} from './funcToClassConversion/funcToClassBasedElementConverter';
+import {LegacyPolymerFuncReplacer} from './funcToClassConversion/legacyPolymerFuncReplacer';
+import {UpdatedFileWriter} from './funcToClassConversion/updatedFileWriter';
+import {CommandLineParser} from './utils/commandLineParser';
+
+interface UpdaterParameters {
+  htmlFiles: Set<string>;
+  jsFiles: Set<string>;
+  out: string;
+  inplace: boolean;
+  writeOutput: boolean;
+  rootDir: string;
+}
+
+interface InputFilesFilter {
+  includeDir(path: string): boolean;
+  includeFile(path: string): boolean;
+}
+
+function addFile(filePath: string, params: UpdaterParameters, filter: InputFilesFilter) {
+  const parsedPath = path.parse(filePath);
+  const ext = parsedPath.ext.toLowerCase();
+  const relativePath = path.relative(params.rootDir, filePath);
+  if(!filter.includeFile(relativePath)) return;
+  if(relativePath.startsWith("../")) {
+    throw new Error(`${filePath} is not in rootDir ${params.rootDir}`);
+  }
+  if(ext === ".html") {
+    params.htmlFiles.add(relativePath);
+  } if(ext === ".js") {
+    params.jsFiles.add(relativePath);
+  }
+}
+
+function addDirectory(dirPath: string, params: UpdaterParameters, recursive: boolean, filter: InputFilesFilter): void {
+  const entries = fs.readdirSync(dirPath, {withFileTypes: true});
+  for(const entry of entries) {
+    const dirEnt = entry as fs.Dirent;
+    const fullPath = path.join(dirPath, dirEnt.name);
+    const relativePath = path.relative(params.rootDir, fullPath);
+    if(dirEnt.isDirectory()) {
+      if (!filter.includeDir(relativePath)) continue;
+      if(recursive) {
+        addDirectory(fullPath, params, recursive, filter);
+      }
+    }
+    else if(dirEnt.isFile()) {
+      addFile(fullPath, params, filter);
+    } else {
+      throw Error(`Unsupported dir entry '${entry.name}' in '${fullPath}'`);
+    }
+  }
+}
+
+async function updateLegacyComponent(component: LegacyPolymerComponent, params: UpdaterParameters) {
+  const classBasedElement: ClassBasedPolymerElement = PolymerFuncToClassBasedConverter.convert(component);
+
+  const replacer = new LegacyPolymerFuncReplacer(component);
+  const replaceResult = replacer.replace(classBasedElement);
+  try {
+    const writer = new UpdatedFileWriter(component, params);
+    writer.write(replaceResult, classBasedElement.eventsComments, classBasedElement.generatedComments);
+  }
+  finally {
+    replaceResult.dispose();
+  }
+}
+
+async function main() {
+  const params: UpdaterParameters = await getParams();
+  if(params.jsFiles.size === 0) {
+    console.log("No files found");
+    return;
+  }
+  const legacyPolymerComponentParser = new LegacyPolymerComponentParser(params.rootDir, params.htmlFiles)
+  for(const jsFile of params.jsFiles) {
+    console.log(`Processing ${jsFile}`);
+    const legacyComponent = await legacyPolymerComponentParser.parse(jsFile);
+    if(legacyComponent) {
+      await updateLegacyComponent(legacyComponent, params);
+      continue;
+    }
+  }
+}
+
+interface CommandLineParameters {
+  src: string[];
+  recursive: boolean;
+  excludes: string[];
+  out: string;
+  inplace: boolean;
+  noOutput: boolean;
+  rootDir: string;
+}
+
+async function getParams(): Promise<UpdaterParameters> {
+  const parser = new CommandLineParser({
+    src: CommandLineParser.createStringArrayOption("src", ".js file or folder to process", []),
+    recursive: CommandLineParser.createBooleanOption("r", "process folder recursive", false),
+    excludes: CommandLineParser.createStringArrayOption("exclude", "List of file prefixes to exclude. If relative file path starts with one of the prefixes, it will be excluded", []),
+    out: CommandLineParser.createStringOption("out", "Output folder.", null),
+    rootDir: CommandLineParser.createStringOption("root", "Root directory for src files", "/"),
+    inplace: CommandLineParser.createBooleanOption("i", "Update files inplace", false),
+    noOutput: CommandLineParser.createBooleanOption("noout", "Do everything, but do not write anything to files", false),
+  });
+  const commandLineParams: CommandLineParameters = parser.parse(process.argv) as CommandLineParameters;
+
+  const params: UpdaterParameters = {
+    htmlFiles: new Set(),
+    jsFiles: new Set(),
+    writeOutput: !commandLineParams.noOutput,
+    inplace: commandLineParams.inplace,
+    out: commandLineParams.out,
+    rootDir: path.resolve(commandLineParams.rootDir)
+  };
+
+  if(params.writeOutput && !params.inplace && !params.out) {
+    throw new Error("You should specify output directory (--out directory_name)");
+  }
+
+  const filter = new ExcludeFilesFilter(commandLineParams.excludes);
+  for(const srcPath of commandLineParams.src) {
+    const resolvedPath = path.resolve(params.rootDir, srcPath);
+    if(fs.lstatSync(resolvedPath).isFile()) {
+      addFile(resolvedPath, params, filter);
+    } else {
+      addDirectory(resolvedPath, params, commandLineParams.recursive, filter);
+    }
+  }
+  return params;
+}
+
+class ExcludeFilesFilter implements InputFilesFilter {
+  public constructor(private readonly excludes: string[]) {
+  }
+  includeDir(path: string): boolean {
+    return this.excludes.every(exclude => !path.startsWith(exclude));
+  }
+
+  includeFile(path: string): boolean {
+    return this.excludes.every(exclude => !path.startsWith(exclude));
+  }
+}
+
+main().then(() => {
+  process.exit(0);
+}).catch(e => {
+  console.error(e);
+  process.exit(1);
+});
diff --git a/tools/polygerrit-updater/src/utils/codeUtils.ts b/tools/polygerrit-updater/src/utils/codeUtils.ts
new file mode 100644
index 0000000..53a7f0d
--- /dev/null
+++ b/tools/polygerrit-updater/src/utils/codeUtils.ts
@@ -0,0 +1,183 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as ts from 'typescript';
+import {SyntaxKind} from 'typescript';
+import {Node} from 'typescript';
+
+export function assertNodeKind<T extends U, U extends ts.Node>(node: U, expectedKind: ts.SyntaxKind): T {
+  if (node.kind !== expectedKind) {
+    throw new Error(`Invlid node kind. Expected: ${ts.SyntaxKind[expectedKind]}, actual: ${ts.SyntaxKind[node.kind]}`);
+  }
+  return node as T;
+}
+
+export function assertNodeKindOrUndefined<T extends U, U extends ts.Node>(node: U | undefined, expectedKind: ts.SyntaxKind): T | undefined {
+  if (!node) {
+    return undefined;
+  }
+  return assertNodeKind<T, U>(node, expectedKind);
+}
+
+export function getPropertyAssignment(expression?: ts.ObjectLiteralElementLike): ts.PropertyAssignment | undefined {
+  return assertNodeKindOrUndefined(expression, ts.SyntaxKind.PropertyAssignment);
+}
+
+export function getStringLiteralValue(expression: ts.Expression): string {
+  const literal: ts.StringLiteral = assertNodeKind(expression, ts.SyntaxKind.StringLiteral);
+  return literal.text;
+}
+
+export function getBooleanLiteralValue(expression: ts.Expression): boolean {
+  if (expression.kind === ts.SyntaxKind.TrueKeyword) {
+    return true;
+  }
+  if (expression.kind === ts.SyntaxKind.FalseKeyword) {
+    return false;
+  }
+  throw new Error(`Invalid expression kind - ${expression.kind}`);
+}
+
+export function getObjectLiteralExpression(expression: ts.Expression): ts.ObjectLiteralExpression {
+  return assertNodeKind(expression, ts.SyntaxKind.ObjectLiteralExpression);
+}
+
+export function getArrayLiteralExpression(expression: ts.Expression): ts.ArrayLiteralExpression {
+  return assertNodeKind(expression, ts.SyntaxKind.ArrayLiteralExpression);
+}
+
+export function replaceNode(file: ts.SourceFile, originalNode: ts.Node, newNode: ts.Node): ts.TransformationResult<ts.SourceFile> {
+  const nodeReplacerTransformer: ts.TransformerFactory<ts.SourceFile> = (context: ts.TransformationContext) => {
+    const visitor: ts.Visitor = (node) => {
+      if(node === originalNode) {
+        return newNode;
+      }
+      return ts.visitEachChild(node, visitor, context);
+    };
+
+
+    return source => ts.visitNode(source, visitor);
+  };
+  return ts.transform(file, [nodeReplacerTransformer]);
+}
+
+export type NameExpression = ts.Identifier | ts.ThisExpression | ts.PropertyAccessExpression;
+export function createNameExpression(fullPath: string): NameExpression {
+  const parts = fullPath.split(".");
+  let result: NameExpression = parts[0] === "this" ? ts.createThis() : ts.createIdentifier(parts[0]);
+  for(let i = 1; i < parts.length; i++) {
+    result = ts.createPropertyAccess(result, parts[i]);
+  }
+  return result;
+}
+
+const generatedCommentNewLineAfterText = "-Generated code - new line after - 9cb292bc-5d88-4c5e-88f4-49535c93beb9 -";
+const generatedCommentNewLineBeforeText = "-Generated code - new line-before - 9cb292bc-5d88-4c5e-88f4-49535c93beb9 -";
+const generatedCommentNewLineAfterRegExp = new RegExp("//" + generatedCommentNewLineAfterText, 'g');
+const generatedCommentNewLineBeforeRegExp = new RegExp("//" + generatedCommentNewLineBeforeText + "\n", 'g');
+const replacableCommentText = "- Replacepoint - 9cb292bc-5d88-4c5e-88f4-49535c93beb9 -";
+
+export function addNewLineAfterNode<T extends ts.Node>(node: T): T {
+  const comment = ts.getSyntheticTrailingComments(node);
+  if(comment && comment.some(c => c.text === generatedCommentNewLineAfterText)) {
+    return node;
+  }
+  return ts.addSyntheticTrailingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, generatedCommentNewLineAfterText, true);
+}
+
+export function addNewLineBeforeNode<T extends ts.Node>(node: T): T {
+  const comment = ts.getSyntheticLeadingComments(node);
+  if(comment && comment.some(c => c.text === generatedCommentNewLineBeforeText)) {
+    return node;
+  }
+  return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, generatedCommentNewLineBeforeText, true);
+}
+
+
+export function applyNewLines(text: string): string {
+  return text.replace(generatedCommentNewLineAfterRegExp, "").replace(generatedCommentNewLineBeforeRegExp, "");
+
+}
+export function addReplacableCommentAfterNode<T extends ts.Node>(node: T, name: string): T {
+  return ts.addSyntheticTrailingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, replacableCommentText + name, true);
+}
+
+export function addReplacableCommentBeforeNode<T extends ts.Node>(node: T, name: string): T {
+  return ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, replacableCommentText + name, true);
+}
+
+export function replaceComment(text: string, commentName: string, newContent: string): string {
+  return text.replace("//" + replacableCommentText + commentName, newContent);
+}
+
+export function createMethod(name: string, methodDecl: ts.MethodDeclaration | undefined, codeAtStart: ts.Statement[], codeAtEnd: ts.Statement[], callSuperMethod: boolean): ts.MethodDeclaration | undefined {
+  if(!methodDecl && (codeAtEnd.length > 0 || codeAtEnd.length > 0)) {
+    methodDecl = ts.createMethod([], [], undefined, name, undefined, [], [],undefined, ts.createBlock([]));
+  }
+  if(!methodDecl) {
+    return;
+  }
+  if (!methodDecl.body) {
+    throw new Error("Method must have a body");
+  }
+  if(methodDecl.parameters.length > 0) {
+    throw new Error("Methods with parameters are not supported");
+  }
+  let newStatements = [...codeAtStart];
+  if(callSuperMethod) {
+    const superCall: ts.CallExpression = ts.createCall(ts.createPropertyAccess(ts.createSuper(), assertNodeKind(methodDecl.name, ts.SyntaxKind.Identifier) as ts.Identifier), [], []);
+    const superCallExpression = ts.createExpressionStatement(superCall);
+    newStatements.push(superCallExpression);
+  }
+  newStatements.push(...codeAtEnd);
+  const newBody = ts.getMutableClone(methodDecl.body);
+
+  newStatements = newStatements.map(m => addNewLineAfterNode(m));
+  newStatements.splice(codeAtStart.length + 1, 0, ...newBody.statements);
+
+  newBody.statements = ts.createNodeArray(newStatements);
+
+  const newMethod = ts.getMutableClone(methodDecl);
+  newMethod.body = newBody;
+
+  return newMethod;
+}
+
+export function restoreLeadingComments<T extends Node>(node: T, originalComments: string[]): T {
+  if(originalComments.length === 0) {
+    return node;
+  }
+  for(const comment of originalComments) {
+    if(comment.startsWith("//")) {
+      node = ts.addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, comment.substr(2), true);
+    } else if(comment.startsWith("/*")) {
+      if(!comment.endsWith("*/")) {
+        throw new Error(`Not support comment: ${comment}`);
+      }
+      node = ts.addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, comment.substr(2, comment.length - 4), true);
+    } else {
+      throw new Error(`Not supported comment: ${comment}`);
+    }
+  }
+  return node;
+}
+
+export function getLeadingComments(node: ts.Node): string[] {
+  const nodeText = node.getFullText();
+  const commentRanges = ts.getLeadingCommentRanges(nodeText, 0);
+  if(!commentRanges) {
+    return [];
+  }
+  return commentRanges.map(range => nodeText.substring(range.pos, range.end))
+}
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/utils/commandLineParser.ts b/tools/polygerrit-updater/src/utils/commandLineParser.ts
new file mode 100644
index 0000000..658b7ff
--- /dev/null
+++ b/tools/polygerrit-updater/src/utils/commandLineParser.ts
@@ -0,0 +1,134 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed un  der the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+export class CommandLineParser {
+  public static createStringArrayOption(optionName: string, help: string, defaultValue: string[]): CommandLineArgument {
+    return new StringArrayOption(optionName, help, defaultValue);
+  }
+  public static createBooleanOption(optionName: string, help: string, defaultValue: boolean): CommandLineArgument {
+    return new BooleanOption(optionName, help, defaultValue);
+  }
+  public static createStringOption(optionName: string, help: string, defaultValue: string | null): CommandLineArgument {
+    return new StringOption(optionName, help, defaultValue);
+  }
+
+  public constructor(private readonly argumentTypes: {[name: string]: CommandLineArgument}) {
+  }
+  public parse(argv: string[]): object {
+    const result = Object.assign({});
+    let index = 2; //argv[0] - node interpreter, argv[1] - index.js
+    for(const argumentField in this.argumentTypes) {
+      result[argumentField] = this.argumentTypes[argumentField].getDefaultValue();
+    }
+    while(index < argv.length) {
+      let knownArgument = false;
+      for(const argumentField in this.argumentTypes) {
+        const argumentType = this.argumentTypes[argumentField];
+        const argumentValue = argumentType.tryRead(argv, index);
+        if(argumentValue) {
+          knownArgument = true;
+          index += argumentValue.consumed;
+          result[argumentField] = argumentValue.value;
+          break;
+        }
+      }
+      if(!knownArgument) {
+        throw new Error(`Unknown argument ${argv[index]}`);
+      }
+    }
+    return result;
+  }
+}
+
+interface CommandLineArgumentReadResult {
+  consumed: number;
+  value: any;
+}
+
+export interface CommandLineArgument {
+  getDefaultValue(): any;
+  tryRead(argv: string[], startIndex: number): CommandLineArgumentReadResult | null;
+}
+
+abstract class CommandLineOption implements CommandLineArgument {
+  protected constructor(protected readonly optionName: string, protected readonly help: string, private readonly defaultValue: any) {
+  }
+  public tryRead(argv: string[], startIndex: number): CommandLineArgumentReadResult | null  {
+    if(argv[startIndex] !== "--" + this.optionName) {
+      return null;
+    }
+    const readArgumentsResult = this.readArguments(argv, startIndex + 1);
+    if(!readArgumentsResult) {
+      return null;
+    }
+    readArgumentsResult.consumed++; // Add option name
+    return readArgumentsResult;
+  }
+  public getDefaultValue(): any {
+    return this.defaultValue;
+  }
+
+  protected abstract readArguments(argv: string[], startIndex: number) : CommandLineArgumentReadResult | null;
+}
+
+class StringArrayOption extends CommandLineOption {
+  public constructor(optionName: string, help: string, defaultValue: string[]) {
+    super(optionName, help, defaultValue);
+  }
+
+  protected readArguments(argv: string[], startIndex: number): CommandLineArgumentReadResult {
+    const result = [];
+    let index = startIndex;
+    while(index < argv.length) {
+      if(argv[index].startsWith("--")) {
+        break;
+      }
+      result.push(argv[index]);
+      index++;
+    }
+    return {
+      consumed: index - startIndex,
+      value: result
+    }
+  }
+}
+
+class BooleanOption extends CommandLineOption {
+  public constructor(optionName: string, help: string, defaultValue: boolean) {
+    super(optionName, help, defaultValue);
+  }
+
+  protected readArguments(argv: string[], startIndex: number): CommandLineArgumentReadResult {
+    return {
+      consumed: 0,
+      value: true
+    }
+  }
+}
+
+class StringOption extends CommandLineOption {
+  public constructor(optionName: string, help: string, defaultValue: string | null) {
+    super(optionName, help, defaultValue);
+  }
+
+  protected readArguments(argv: string[], startIndex: number): CommandLineArgumentReadResult | null {
+    if(startIndex >= argv.length) {
+      return null;
+    }
+    return {
+      consumed: 1,
+      value: argv[startIndex]
+    }
+  }
+}
diff --git a/tools/polygerrit-updater/src/utils/commentsParser.ts b/tools/polygerrit-updater/src/utils/commentsParser.ts
new file mode 100644
index 0000000..b849829
--- /dev/null
+++ b/tools/polygerrit-updater/src/utils/commentsParser.ts
@@ -0,0 +1,79 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+enum CommentScannerState {
+  Text,
+  SingleLineComment,
+  MultLineComment
+}
+export class CommentsParser {
+  public static collectAllComments(text: string): string[] {
+    const result: string[] = [];
+    let state = CommentScannerState.Text;
+    let pos = 0;
+    function readSingleLineComment() {
+      const startPos = pos;
+      while(pos < text.length && text[pos] !== '\n') {
+        pos++;
+      }
+      return text.substring(startPos, pos);
+    }
+    function readMultiLineComment() {
+      const startPos = pos;
+      while(pos < text.length) {
+        if(pos < text.length - 1 && text[pos] === '*' && text[pos + 1] === '/') {
+          pos += 2;
+          break;
+        }
+        pos++;
+      }
+      return text.substring(startPos, pos);
+    }
+
+    function skipString(lastChar: string) {
+      pos++;
+      while(pos < text.length) {
+        if(text[pos] === lastChar) {
+          pos++;
+          return;
+        } else if(text[pos] === '\\') {
+          pos+=2;
+          continue;
+        }
+        pos++;
+      }
+    }
+
+
+    while(pos < text.length - 1) {
+      if(text[pos] === '/' && text[pos + 1] === '/') {
+        result.push(readSingleLineComment());
+      } else if(text[pos] === '/' && text[pos + 1] === '*') {
+        result.push(readMultiLineComment());
+      } else if(text[pos] === "'") {
+        skipString("'");
+      } else if(text[pos] === '"') {
+        skipString('"');
+      } else if(text[pos] === '`') {
+        skipString('`');
+      } else if(text[pos] == '/') {
+        skipString('/');
+      } {
+        pos++;
+      }
+
+    }
+    return result;
+  }
+}
diff --git a/tools/polygerrit-updater/src/utils/polymerClassBuilder.ts b/tools/polygerrit-updater/src/utils/polymerClassBuilder.ts
new file mode 100644
index 0000000..b1a4320
--- /dev/null
+++ b/tools/polygerrit-updater/src/utils/polymerClassBuilder.ts
@@ -0,0 +1,270 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as ts from 'typescript';
+import * as codeUtils from './codeUtils';
+import {LegacyLifecycleMethodName, LegacyLifecycleMethodsArray} from '../funcToClassConversion/polymerComponentParser';
+import {SyntaxKind} from 'typescript';
+
+enum PolymerClassMemberType {
+  IsAccessor,
+  Constructor,
+  PolymerPropertiesAccessor,
+  PolymerObserversAccessor,
+  Method,
+  ExistingLifecycleMethod,
+  NewLifecycleMethod,
+  GetAccessor,
+}
+
+type PolymerClassMember = PolymerClassIsAccessor | PolymerClassConstructor | PolymerClassExistingLifecycleMethod | PolymerClassNewLifecycleMethod | PolymerClassSimpleMember;
+
+interface PolymerClassExistingLifecycleMethod {
+  member: ts.MethodDeclaration;
+  memberType: PolymerClassMemberType.ExistingLifecycleMethod;
+  name: string;
+  lifecycleOrder: number;
+  originalPos: number;
+}
+
+interface PolymerClassNewLifecycleMethod {
+  member: ts.MethodDeclaration;
+  memberType: PolymerClassMemberType.NewLifecycleMethod;
+  name: string;
+  lifecycleOrder: number;
+  originalPos: -1
+}
+
+interface PolymerClassIsAccessor {
+  member: ts.GetAccessorDeclaration;
+  memberType: PolymerClassMemberType.IsAccessor;
+  originalPos: -1
+}
+
+interface PolymerClassConstructor {
+  member: ts.ConstructorDeclaration;
+  memberType: PolymerClassMemberType.Constructor;
+  originalPos: -1
+}
+
+interface PolymerClassSimpleMember {
+  memberType: PolymerClassMemberType.PolymerPropertiesAccessor | PolymerClassMemberType.PolymerObserversAccessor | PolymerClassMemberType.Method | PolymerClassMemberType.GetAccessor;
+  member: ts.ClassElement;
+  originalPos: number;
+}
+
+export interface PolymerClassBuilderResult {
+  classDeclaration: ts.ClassDeclaration;
+  generatedComments: string[];
+}
+
+export class PolymerClassBuilder {
+  private readonly members: PolymerClassMember[] = [];
+  public readonly constructorStatements: ts.Statement[] = [];
+  private baseType: ts.ExpressionWithTypeArguments | undefined;
+  private classJsDocComments: string[];
+
+  public constructor(public readonly className: string) {
+    this.classJsDocComments = [];
+  }
+
+  public addIsAccessor(accessor: ts.GetAccessorDeclaration) {
+    this.members.push({
+      member: accessor,
+      memberType: PolymerClassMemberType.IsAccessor,
+      originalPos: -1
+    });
+  }
+
+  public addPolymerPropertiesAccessor(originalPos: number, accessor: ts.GetAccessorDeclaration) {
+    this.members.push({
+      member: accessor,
+      memberType: PolymerClassMemberType.PolymerPropertiesAccessor,
+      originalPos: originalPos
+    });
+  }
+
+  public addPolymerObserversAccessor(originalPos: number, accessor: ts.GetAccessorDeclaration) {
+    this.members.push({
+      member: accessor,
+      memberType: PolymerClassMemberType.PolymerObserversAccessor,
+      originalPos: originalPos
+    });
+  }
+
+
+  public addClassFieldInitializer(name: string | ts.Identifier, initializer: ts.Expression) {
+    const assignment = ts.createAssignment(ts.createPropertyAccess(ts.createThis(), name), initializer);
+    this.constructorStatements.push(codeUtils.addNewLineAfterNode(ts.createExpressionStatement(assignment)));
+  }
+  public addMethod(originalPos: number, method: ts.MethodDeclaration) {
+    this.members.push({
+      member: method,
+      memberType: PolymerClassMemberType.Method,
+      originalPos: originalPos
+    });
+  }
+
+  public addGetAccessor(originalPos: number, accessor: ts.GetAccessorDeclaration) {
+    this.members.push({
+      member: accessor,
+      memberType: PolymerClassMemberType.GetAccessor,
+      originalPos: originalPos
+    });
+  }
+
+  public addLifecycleMethod(name: LegacyLifecycleMethodName, originalPos: number, method: ts.MethodDeclaration) {
+    const lifecycleOrder = LegacyLifecycleMethodsArray.indexOf(name);
+    if(lifecycleOrder < 0) {
+      throw new Error(`Invalid lifecycle name`);
+    }
+    if(originalPos >= 0) {
+      this.members.push({
+        member: method,
+        memberType: PolymerClassMemberType.ExistingLifecycleMethod,
+        originalPos: originalPos,
+        name: name,
+        lifecycleOrder: lifecycleOrder
+      })
+    } else {
+      this.members.push({
+        member: method,
+        memberType: PolymerClassMemberType.NewLifecycleMethod,
+        name: name,
+        lifecycleOrder: lifecycleOrder,
+        originalPos: -1
+      })
+    }
+  }
+
+  public setBaseType(type: ts.ExpressionWithTypeArguments) {
+    if(this.baseType) {
+      throw new Error("Class can have only one base type");
+    }
+    this.baseType = type;
+  }
+
+  public build(): PolymerClassBuilderResult {
+    let heritageClauses: ts.HeritageClause[] = [];
+    if (this.baseType) {
+      const extendClause = ts.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [this.baseType]);
+      heritageClauses.push(extendClause);
+    }
+    const finalMembers: PolymerClassMember[] = [];
+    const isAccessors = this.members.filter(member => member.memberType === PolymerClassMemberType.IsAccessor);
+    if(isAccessors.length !== 1) {
+      throw new Error("Class must have exactly one 'is'");
+    }
+    finalMembers.push(isAccessors[0]);
+    const constructorMember = this.createConstructor();
+    if(constructorMember) {
+      finalMembers.push(constructorMember);
+    }
+
+    const newLifecycleMethods: PolymerClassNewLifecycleMethod[] = [];
+    this.members.forEach(member => {
+      if(member.memberType === PolymerClassMemberType.NewLifecycleMethod) {
+        newLifecycleMethods.push(member);
+      }
+    });
+
+    const methodsWithKnownPosition = this.members.filter(member => member.originalPos >= 0);
+    methodsWithKnownPosition.sort((a, b) => a.originalPos - b.originalPos);
+
+    finalMembers.push(...methodsWithKnownPosition);
+
+
+    for(const newLifecycleMethod of newLifecycleMethods) {
+      //Number of methods is small - use brute force solution
+      let closestNextIndex = -1;
+      let closestNextOrderDiff: number = LegacyLifecycleMethodsArray.length;
+      let closestPrevIndex = -1;
+      let closestPrevOrderDiff: number = LegacyLifecycleMethodsArray.length;
+      for (let i = 0; i < finalMembers.length; i++) {
+        const member = finalMembers[i];
+        if (member.memberType !== PolymerClassMemberType.NewLifecycleMethod && member.memberType !== PolymerClassMemberType.ExistingLifecycleMethod) {
+          continue;
+        }
+        const orderDiff = member.lifecycleOrder - newLifecycleMethod.lifecycleOrder;
+        if (orderDiff > 0) {
+          if (orderDiff < closestNextOrderDiff) {
+            closestNextIndex = i;
+            closestNextOrderDiff = orderDiff;
+          }
+        } else if (orderDiff < 0) {
+          if (orderDiff < closestPrevOrderDiff) {
+            closestPrevIndex = i;
+            closestPrevOrderDiff = orderDiff;
+          }
+        }
+      }
+      let insertIndex;
+      if (closestNextIndex !== -1 || closestPrevIndex !== -1) {
+        insertIndex = closestNextOrderDiff < closestPrevOrderDiff ?
+            closestNextIndex : closestPrevIndex + 1;
+      } else {
+        insertIndex = Math.max(
+            finalMembers.findIndex(m => m.memberType === PolymerClassMemberType.Constructor),
+            finalMembers.findIndex(m => m.memberType === PolymerClassMemberType.IsAccessor),
+            finalMembers.findIndex(m => m.memberType === PolymerClassMemberType.PolymerPropertiesAccessor),
+            finalMembers.findIndex(m => m.memberType === PolymerClassMemberType.PolymerObserversAccessor),
+        );
+        if(insertIndex < 0) {
+          insertIndex = finalMembers.length;
+        } else {
+          insertIndex++;//Insert after
+        }
+      }
+      finalMembers.splice(insertIndex, 0, newLifecycleMethod);
+    }
+    //Asserts about finalMembers
+    const nonConstructorMembers = finalMembers.filter(m => m.memberType !== PolymerClassMemberType.Constructor);
+
+    if(nonConstructorMembers.length !== this.members.length) {
+      throw new Error(`Internal error! Some methods are missed`);
+    }
+    let classDeclaration = ts.createClassDeclaration(undefined, undefined, this.className, undefined, heritageClauses, finalMembers.map(m => m.member))
+    const generatedComments: string[] = [];
+    if(this.classJsDocComments.length > 0) {
+      const commentContent = '*\n' + this.classJsDocComments.map(line => `* ${line}`).join('\n') + '\n';
+      classDeclaration = ts.addSyntheticLeadingComment(classDeclaration, ts.SyntaxKind.MultiLineCommentTrivia, commentContent, true);
+      generatedComments.push(`/*${commentContent}*/`);
+    }
+    return {
+      classDeclaration,
+      generatedComments,
+    };
+
+  }
+
+  private createConstructor(): PolymerClassConstructor | null {
+    if(this.constructorStatements.length === 0) {
+      return null;
+    }
+    let superCall: ts.CallExpression = ts.createCall(ts.createSuper(), [], []);
+    const superCallExpression = ts.createExpressionStatement(superCall);
+    const statements = [superCallExpression, ...this.constructorStatements];
+    const constructorDeclaration = ts.createConstructor([], [], [], ts.createBlock(statements, true));
+
+    return {
+      memberType: PolymerClassMemberType.Constructor,
+      member: constructorDeclaration,
+      originalPos: -1
+    };
+  }
+
+  public addClassJSDocComments(lines: string[]) {
+    this.classJsDocComments.push(...lines);
+  }
+}
\ No newline at end of file
diff --git a/tools/polygerrit-updater/src/utils/unexpectedValue.ts b/tools/polygerrit-updater/src/utils/unexpectedValue.ts
new file mode 100644
index 0000000..690c283
--- /dev/null
+++ b/tools/polygerrit-updater/src/utils/unexpectedValue.ts
@@ -0,0 +1,17 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+export function unexpectedValue<T>(x: T): never {
+  throw new Error(`Unexpected value '${x}'`);
+}
diff --git a/tools/polygerrit-updater/tsconfig.json b/tools/polygerrit-updater/tsconfig.json
new file mode 100644
index 0000000..37ff1b2
--- /dev/null
+++ b/tools/polygerrit-updater/tsconfig.json
@@ -0,0 +1,67 @@
+{
+  "compilerOptions": {
+    /* Basic Options */
+    // "incremental": true,                   /* Enable incremental compilation */
+    "target": "es2015",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
+    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
+    // "lib": [],                             /* Specify library files to be included in the compilation. */
+    // "allowJs": true,                       /* Allow javascript files to be compiled. */
+    // "checkJs": true,                       /* Report errors in .js files. */
+    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
+    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
+    "sourceMap": true,                     /* Generates corresponding '.map' file. */
+    // "outFile": "./",                       /* Concatenate and emit output to single file. */
+    "outDir": "./js",                        /* Redirect output structure to the directory. */
+    "rootDir": ".",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+    // "composite": true,                     /* Enable project compilation */
+    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
+    // "removeComments": true,                /* Do not emit comments to output. */
+    // "noEmit": true,                        /* Do not emit outputs. */
+    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
+    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+    /* Strict Type-Checking Options */
+    "strict": true,                           /* Enable all strict type-checking options. */
+    "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,              /* Enable strict null checks. */
+    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
+    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
+    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
+
+    /* Additional Checks */
+    // "noUnusedLocals": true,                /* Report errors on unused locals. */
+    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
+    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
+
+    /* Module Resolution Options */
+    "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+    "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
+    "paths": {
+      "*": [ "node_modules/*" ]
+    },                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
+    // "typeRoots": [],                       /* List of folders to include type definitions from. */
+    // "types": [],                           /* Type declaration files to be included in compilation. */
+    "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
+    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
+
+    /* Source Map Options */
+    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
+    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+    /* Experimental Options */
+    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
+    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
+
+  },
+  "include": ["./src/**/*"]
+}